Search Unity

[RELEASED] StrangeIoC - Inversion-of-Control Framework for Unity C#

Discussion in 'Assets and Asset Store' started by srimarc, Jun 13, 2013.

  1. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    Yes don't be careful an old copy past from an old loadscene manager model.

    Code (csharp):
    1. using System;
    2. using UnityEngine;
    3. using System.Collections;
    4. using strange.extensions.context.api;
    5. using strange.extensions.command.impl;
    6. using strange.extensions.dispatcher.eventdispatcher.impl;
    7. using strange.extensions.dispatcher.eventdispatcher.api;
    8.  
    9. public class Main_LoadSceneCommand : EventCommand
    10. {
    11.    
    12.     [Inject(ContextKeys.CONTEXT_VIEW)]
    13.     public GameObject contextView{get;set;}
    14.    
    15.     [Inject(ContextKeys.CONTEXT)]
    16.     public IContext context{get;set;}
    17.    
    18.     [Inject]
    19.     public ISceneManager scenemanager{get;set;}
    20.    
    21.     [Inject(ContextKeys.CROSS_CONTEXT_DISPATCHER)]
    22.     public IEventDispatcher crossContextDispatcher{get;set;}
    23.  
    24.        
    25.     public override void Execute()
    26.     {
    27.         string filepath = evt.data as string;
    28.         UpdateListener(true);  
    29.         LoadScene(filepath);
    30.     }
    31.    
    32.     public void LoadScene (string _filepath)
    33.     {      
    34.         if(scenemanager.CurrentScenePath != _filepath)
    35.         {
    36.             GameObject[] contextobj = GameObject.FindGameObjectsWithTag(TagManager.Context);
    37.            
    38.             foreach(GameObject o in contextobj)
    39.             {
    40.                 GameObject.Destroy(o);
    41.             }
    42.            
    43.             Main_Root root = GameObject.FindGameObjectWithTag(TagManager.MainContext).GetComponent<Main_Root>();
    44.            
    45.             root.StartCoroutine(loadSene(_filepath));
    46.            
    47.             scenemanager.CurrentScenePath = _filepath;//la scene courante
    48.         }
    49.         else
    50.         {
    51.             Debug.Log("Pas de load a faire");
    52.             return;
    53.         }
    54.     }
    55.    
    56.     public IEnumerator loadSene(string filepath)
    57.     {
    58.         AsyncOperation async =  Application.LoadLevelAdditiveAsync(filepath);
    59.         yield return async;
    60.         OnComplete();
    61.     }
    62.    
    63.     public void UpdateListener(bool _value)
    64.     {
    65.         dispatcher.UpdateListener(_value,APP_Event.GETUSECONTEXT,GetUseContext);
    66.         dispatcher.UpdateListener(_value,APP_Event.GETDESCRIPTIONCONTEXT,GetDescriptionContext);
    67.     }
    68.    
    69.     public void OnComplete()
    70.     {
    71.         UpdateListener(false);
    72.         crossContextDispatcher.Dispatch(APP_Event.SCENEISLOADED);
    73.     }
    74.    
    75.     public void GetUseContext(IEvent ievt)
    76.     {
    77.         IContext cnt = ievt.data as IContext;
    78.         Debug.Log("recup use context : "+ cnt);
    79.     }
    80.    
    81.     public void GetDescriptionContext(IEvent ievt)
    82.     {
    83.         IContext cnt = ievt.data as IContext;
    84.         Debug.Log("recup description context : "+cnt);
    85.     }
    86.  
    in my use_start_commant "scene Use" i cross contextdispatch with the context for payload.
    when i load my scene i can debug in correctly in unity !

    Code (csharp):
    1.  
    2. using System;
    3. using UnityEngine;
    4. using System.Collections;
    5. using strange.extensions.context.api;
    6. using strange.extensions.command.impl;
    7. using strange.extensions.dispatcher.eventdispatcher.impl;
    8. using strange.extensions.dispatcher.eventdispatcher.api;
    9.  
    10.  
    11. public class Use_StartCommand : EventCommand
    12. {
    13.     [Inject(ContextKeys.CONTEXT)]
    14.     public IContext context{get;set;}
    15.    
    16.     [Inject(ContextKeys.CONTEXT_VIEW)]
    17.     public GameObject contextView{get;set;}
    18.    
    19.     [Inject(ContextKeys.CROSS_CONTEXT_DISPATCHER)]
    20.     public IEventDispatcher crosscontextdispatcher{get;set;}
    21.    
    22.     public override void Execute()
    23.     {
    24.         GameObject go = new GameObject();
    25.         go.name = "Use_View";
    26.         go.transform.parent = contextView.transform;
    27.         go.AddComponent<Use_View>();
    28.        
    29.         //Debug.Log("context courant : "+context);
    30.         crosscontextdispatcher.Dispatch(APP_Event.GETUSECONTEXT,context);//dispatch for removal
    31.     }
    32. }
    33.  
    I do exactly the same thing for my description "scene" when i load my scene i have an error :

    Code (csharp):
    1.  
    2.  
    3. using System;
    4. using UnityEngine;
    5. using System.Collections;
    6. using strange.extensions.context.api;
    7. using strange.extensions.command.impl;
    8. using strange.extensions.dispatcher.eventdispatcher.impl;
    9. using strange.extensions.dispatcher.eventdispatcher.api;
    10.  
    11. public class Description_StartCommand : EventCommand
    12. {
    13.    
    14.     [Inject(ContextKeys.CONTEXT)]
    15.     public IContext context{get;set;}
    16.    
    17.     [Inject(ContextKeys.CONTEXT_VIEW)]
    18.     public GameObject contextView{get;set;}
    19.    
    20.     [Inject]
    21.     public IManager manager{get;set;}
    22.    
    23.     public override void Execute()
    24.     {
    25.        
    26.         GameObject go = new GameObject();
    27.         go.name = "Description_View";
    28.         go.AddComponent<Description_View>();
    29.         go.transform.parent = contextView.transform;
    30.        
    31.        
    32.         Debug.Log("context courant d :" +context);
    33.         crosscontextdispatcher.Dispatch(APP_Event.GETDESCRIPTIONCONTEXT,context);//dispatch for removal
    34.        
    35.         KGFOrbitCamSettings kgfs = GameObject.Find("KGFS_Helicopter").GetComponent<KGFOrbitCamSettings>();
    36.         kgfs.Apply();
    37.  
    38.         //dispatcher.Dispatch(APP_Event.READXML);
    39.    
    40.     }
    41. }
    42.  
    I use the same technics for load my two scenes, one is ok but not the other.
    I really missing some thing :confused:

    "since i write the post i discover that my description_context inject context that is not good i think.
    When i remove the injection all work good for now.

    so now i tryed to pass my context that come from my payload to my scenemanager for stock it for a later removal

    loadscenecommand update the execute with my remove

    Code (csharp):
    1. public void LoadScene (string _filepath)
    2.     {      
    3.         if(scenemanager.CurrentScenePath != _filepath)
    4.         {
    5.             GameObject[] contextobj = GameObject.FindGameObjectsWithTag(TagManager.Context);
    6.            
    7.             if(_filepath == APP_Scene.Main_Menu_Setup  scenemanager.Removablecontext != null)//destruct if i load main_menu
    8.             {
    9.                 Debug.Log("context a detruire : "+scenemanager.Removablecontext);//remove it
    10.                
    11.                 //it
    12.                 Main_Context.firstContext.RemoveContext(scenemanager.Removablecontext);
    13.                 //or
    14.                 //context.RemoveContext(scenemanager.Removablecontext);
    15.             }
    16.            
    17.             foreach(GameObject o in contextobj)
    18.             {
    19.                 GameObject.Destroy(o);
    20.             }
    21.            
    22.             Main_Root root = GameObject.FindGameObjectWithTag(TagManager.MainContext).GetComponent<Main_Root>();
    23.            
    24.             root.StartCoroutine(loadSene(_filepath));
    25.            
    26.             scenemanager.CurrentScenePath = _filepath;//la scene courante
    27.         }
    28.         else
    29.         {
    30.             Debug.Log("Pas de load a faire");
    31.             return;
    32.         }
    33.     }
    34. public void GetUseContext(IEvent ievt)
    35.     {
    36.         IContext cnt = ievt.data as IContext;
    37.         scenemanager.Removablecontext = cnt;//give it to manager in case use scene
    38.         Debug.Log("recup use context : "+ cnt);
    39.     }
    40.    
    41.     public void GetDescriptionContext(IEvent ievt)
    42.     {
    43.         IContext cnt = ievt.data as IContext;
    44.         scenemanager.Removablecontext = cnt;//give it to manager in case description scene
    45.         Debug.Log("recup description context : "+cnt);
    46.     }
    47.  
    48.  
    So when i load my description scene i debug and assign my context to my manager but when i come back to main menu it try to remove my removable context and it tell to me

    I really don't understand the concept somewhere.

    Thanks to your time, if you don't see the purpose we will see that at your come back and give you or project to see in unity.
    I let you alone !

    Good holiday
     
  2. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    Wow...a lot to absorb there. Again, a few things stand out.

    - You don't inject into contexts. And even if you did, injecting ContextKeys.Context would just give you back 'this'.
    - If you want to get the main Context, use the property
    Code (csharp):
    1. Context.firstContext
    . This is a static property containing a reference to the first Context to instantiate.
    - If you want some other Context, crossContextDispatch each Context to a Command which injects a model whose job it is to track them all. Almost inevitably, the tracking Context should be firstContext.
    - The circular dependency exception is just what it sounds like: somewhere you have two classes injecting each other (possibly the circle is broader...like one class that injects a second class which injects a third class...which injects the first class). These can be hard to debug but there's not much I can do for you on that. You'll have to figure it out as best you can.
    - The IndexOutOfRangeException is probably just a symptom of the overall matter of not removing Contexts cleanly. The only hook that any Context has other than its GameObject is its listener to the CrossContextDispatcher. The stack trace you're seeing is probably an indication that the context is being destroyed because its GameObject has been destroyed...but removeContext was not successfully called. Put a break point into MVCSContext.removeContext and confirm that it's being called.

    It seems there might be more than a single issue here. I'd suggest simpifying: build a simple project where you can demonstrate adding and removing Contexts without all the other parts. Once you can do that cleanly, you can port the example code into the more complex app.
     
  3. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    hi and thanks for reply

    i debug it and the loop come from my injection in description context when i remove my injection i sucessfully send my context by crosscontextdispatch !

    You are right tomorow i try to make a simple text for multi load and unload !

    thanks
     
  4. Deleted User

    Deleted User

    Guest

    I've started using this framework and found it pretty nice so far, at least once I got comfortable with the proposed model. :)

    I'm struggling to find the right way to tie together some pieces of the model and view, however. I have a PeopleManagerModel which contains a bunch of PeopleModel for individual people in the game. I have a PeopleManagerView/Mediator pair for interacting with Unity at the manager level but I also need to have PeopleView/Mediators for individual people. However the people can come/go from the simulation space. That is, they can go into a building and I'd like at that time to remove them from the Unity scene entirely to avoid extra processing and rendering when they are inactive.

    Is there a good way to set up a prefab and the MVC stuff such that I can create an instance of a prefab and have it look up a specific instance of the IPeopleModel, pulled from my manager model?
     
  5. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    It's a standard problem in game design to have a view which wants to be tightly coupled to a model. Strange allows many possible approaches to this problem, but I'll share my favorite. At the end, I'll talk specifically to your question of filing and retrieving specific instances.

    Also note that I'm on vacation...so I'm doing some of this from memory. YOU HAVE BEEN WARNED!

    When game logic decides it's time to launch one or more new People (using your example), I'd have a GameEvent.INIT_PERSON mapped to an InitPersonCommand. InitPersonCommand probably injects PeopleManager...a collection to manage all the PersonModels. The notion of a ManagerView/Mediator pair strikes me as incorrect. Views are for display. Management is properly the province of Models and Controllers.

    Now, because the PersonView has a tight relationship to the model, it probably makes sense to create a personModel property and set that on the View. I don't encourage this structure generally, but when there are many View instances tightly coupled to multiple model instances (a many-to-many relationship) I've found this to be a simple, effective handling technique. The PersonView now exists, and has a reference to the PersonModel. I rarely if ever allow my Models references to their Views...they use Dispatchers to issue changes in state, and because of the tight coupling in this example, the View can choose to listen to those changes directly.

    There are two basic ways that such Views usually get destroyed. Either something happens in a model or controller (e.g., the level ends or the PersonModel moves out of the "game area") or something affects the View directly (a MonoBehaviour detects a 'hit' that destroys the View). Either way, we issue a GameEvent.DESTROY_PERSON event, mapped to a DestroyPersonCommand. If this comes from the View, the Mediator issues the event. If it comes from elsewhere, it probably gets issued from a separate Command. DestroyPersonCommand destroys the View, of course, and optionally removes it from the PeopleManager.

    Now, in your case it sounds like the Person is never really destroyed. Rather, she moves to a non-displayable location. The View is removed, but the model is retained within the PeopleManager. Perhaps she even continues to be simulated in memory so she can reappear when needed. So look here:

    Code (csharp):
    1.  
    2. [Inject]
    3. public IInjectionBinder injectionBinder{get;set;}
    4.  
    5. //some method to insure unique instance names. I'm using ints here, but you'll get the idea.
    6. static int uID = 0;
    7.  
    8. // return a new PersonModel
    9. public IPersonModel Get()
    10. {
    11.     IPersonModel model = injectionBinder.GetInstance(IPersonModel);
    12.     int uid = uID ++;
    13.     model.name = uid;
    14.     //Create a named binding
    15.     injectionBinder.Bind<IPersonModel>().ToValue(model).ToName(uid);
    16. }
    17.  
    18. public IPersonModel Get(int value)
    19. {
    20.     IBinding binding = injectionBinder.GetInstance<IPersonModel>().Named(value);
    21.     if (binding == null)
    22.         return Get();  //no such instance found...create a new one
    23.     return binding.value as IPersonModel;
    24. }
    25.  
    26. public void DestroyInstance(int value)
    27. {
    28.     IBinding binding = injectionBinder.GetInstance<IPersonModel>().Named(value);
    29.     if (binding != null)
    30.         injectionBinder.Unbind<IPersonModel>().Named(value);
    31. }
    32.  
    In this way, you can create, read, update and destroy the models as necessary. The named injections keep them neatly filed for you for as long as you need them. You'll probably want to keep a HashSet of the named you've filed, just so you can add a DestroyAll method when you want to clean up indiscriminately.

    You mention a specific prefab that can call on the Manager to get a specific model instance. This is nothing more than Get()ting the uniquely mapped name which you attach to the prefab. (This is probably better done with strings or Enums than the ints I used...hopefully the idea is clear enough and you can see how you'd easily create a list of names.)

    I think that covers it. Hope it's helpful! :)
     
  6. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    ...and under the heavy influence of Sangria. Let me know if I adequately answered your question! :)
     
  7. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    Hi srimarc,

    I made a restritive example to show my probleme for remove context while the load and unload of scene for multi context app.

    I try to explain more significatly my bugs and how i manage the crosscontextdispatcher for communicate my context to the main scene.


    i start my app in a scene call main_scene in this scene i made a main_root witch is construct a main_context, in this main context i map a startcommand
    and a loadscenecommand. In my main_startcommand i dispatch my Main_event.loadscene with a payload that is the name of the scene i wan't to load.

    Code (csharp):
    1.  
    2. public class Main_StartCommand : EventCommand
    3. {
    4.    
    5.     [Inject(ContextKeys.CONTEXT_VIEW)]
    6.     public GameObject contextView{get;set;}
    7.    
    8.     public override void Execute()
    9.     {
    10.         Debug.Log("main is start");
    11.         dispatcher.Dispatch(Main_Event.LOAD_SCENE, "Menu");
    12.         dispatcher.Dispatch(Main_Event.LOAD_SCENE, "Gui");
    13.     }
    14. }
    15.  
    All work as attempt i load my gui scene and menu_scene !

    In my gui i made a view and a mediator to manage it. I made two buttons named "menu" and "level01", this buttons are here to call the menu scene and level01.

    When i click on my gui button i trace the command. I inject directly the crosscontextdispatcher in my gui_mediator. I use it to crosscontextdispatch my loadscene.

    Code (csharp):
    1.  
    2. public class Gui_Mediator : EventMediator
    3. {
    4.     [Inject]
    5.     public Gui_View view{ get; set;}
    6.    
    7.     [Inject(ContextKeys.CROSS_CONTEXT_DISPATCHER)]
    8.     public IEventDispatcher crosscontextdispatcher{ get; set;}
    9.    
    10.     public override void OnRegister()
    11.     {
    12.         UpdateListeners(true);
    13.         view.init ();
    14.     }
    15.    
    16.     public override void OnRemove()
    17.     {
    18.         UpdateListeners(false);
    19.     }
    20.    
    21.     private void UpdateListeners(bool value)
    22.     {
    23.         view.dispatcher.UpdateListener(value,Gui_Event.CLICK,LoadScene);
    24.     }
    25.    
    26.     private void LoadScene(IEvent evt)
    27.     {
    28.         string scenename = evt.data as string;
    29.         crosscontextdispatcher.Dispatch(Main_Event.LOAD_SCENE,scenename);
    30.         Debug.Log("gui load : "+ scenename);
    31.     }
    32. }
    33.  
    My gui is always present in my app so i don't need to manage his context but i wan't to be able to clearly remove my menu_context to load my level01 context and vis versa !

    So eatch time i load my menu or my level01 i made a start_command use to stock the context in a scenemanager mapped as singleton in my main_context.

    EX:

    In my menu when it load in my Menu_Start_Command i crosscontextdispatch my context
    Code (csharp):
    1.  
    2. public override void Execute()
    3.     {
    4.         Debug.Log("menu is start");
    5.         crosscontextdispatcher.Dispatch(Main_Event.GET_CURRENT_CONTEXT,context);
    6.        
    7.     }
    8.  
    Same in my level01

    Code (csharp):
    1. using System;
    2. using UnityEngine;
    3. using strange.extensions.context.api;
    4. using strange.extensions.command.impl;
    5. using strange.extensions.dispatcher.eventdispatcher.impl;
    6.  
    7. public class Main_GetCurrentContext : EventCommand
    8. {
    9.     [Inject]
    10.     public ISceneManager scenemanager{get;set;}
    11.    
    12.     public override void Execute()
    13.     {
    14.         IContext currentcontext = evt.data as IContext;
    15.         scenemanager.LoadedContext = currentcontext;
    16.         Debug.Log("stock le context courant : "+scenemanager.LoadedContext);
    17.     }
    18. }
    Now my loadsceneManager get the currentloadedcontext to clearly remove it !
    Code (csharp):
    1. public class Main_LoadSceneCommand : EventCommand
    2. {
    3.    
    4.     [Inject]
    5.     public ISceneManager scenemanager{get;set;}
    6.    
    7.     public override void Execute()
    8.     {
    9.         string filepath = evt.data as string;
    10.        
    11.         if(scenemanager.LoadedContext != null)
    12.         {
    13.             Debug.Log("context to remove : "+scenemanager.LoadedContext);
    14.             GameObject contextgo = scenemanager.LoadedContext.GetContextView() as GameObject;
    15.             //Context.firstContext.RemoveContext(scenemanager.LoadedContext);
    16.             GameObject.Destroy(contextgo);
    17.            
    18.         }
    19.        
    20.         //Load the component
    21.        
    22.         if (String.IsNullOrEmpty(filepath))
    23.         {
    24.             throw new Exception("Can't load a module with a null or empty filepath.");
    25.         }
    26.         Application.LoadLevelAdditive(filepath);
    27.     }
    28. }
    29.  
    So as you can see in the last script in my loadscenecommand i get the mapped scenemanager, i get the contextview from the context stock in. when i debug it all is good i have in my console "context to remove : Menu_Context".

    i first remove context and bam error
    when i commant the line for the remove i then destroy the gameobject and all is ok it remove clearly with no probleme !

    I'm sorry to anoiying you with that, but i really don't see the problem.

    This is my really last message i contact you when come back to see that !!!

    Thanks again
     
  8. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    PicPic,

    That was a very informative post. It looks very like there's a legitimate bug here. Since I have only a tablet and no laptop while on vacation, I can only suggest a possible fix, not actually write one. I'll try to work it out shortly and post it to you for you to verify. The short of it is that it seems likely that Strange isn't properly disposing of your Context...so the error is probably mine, not yours. I'll post again when I've worked out the details of the fix.
     
  9. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    That a good news for me, i ll stop to blow my mind with a possible fix, but don't be affraid and don't wast your time on holiday, i can wait and we can see that after the 30.

    Thanks again
     
  10. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    Try this: in MVCSContext.RemoveContext() add a new line, like so.

    Code (csharp):
    1.  
    2.         override public IContext RemoveContext(IContext context)
    3.         {
    4.             context.crossContextDispatcher.RemoveTriggerable(context.GetComponent<IEventDispatcher>(ContextKeys.CONTEXT_DISPATCHER);    //new line here
    5.             context.crossContextDispatcher = null;
    6.             return this;
    7.         }
    8.  
    I think this is the missing line that will properly remove the context's EventDispatcher from the crossContextDispatcher. Do please let me know whether or not it works. :)
     
  11. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    Thanks,

    I will test that tomorow i have not my project for test it.
     
  12. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    hi

    the new line was present i think,

    Code (csharp):
    1.  
    2. override public IContext RemoveContext(IContext context)
    3.                {
    4.                        ((context.crossContextDispatcher) as ITriggerProvider).RemoveTriggerable(context.GetComponent<IEventDispatcher>(ContextKeys.CONTEXT_DISPATCHER) as ITriggerable);
    5.                        context.crossContextDispatcher = null;
    6.                        return this;
    7.                }
    8.  
    but when i replace with your current line

    I have this casting error !
     
  13. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    Ah damn. I was looking at a local copy of the codebase...which I guess is out of date. That first line you already have is simply a better form of what I was trying to give you (that line is completely missing from my local copy). I assumed that the absence of that line explained the error you were getting. Since it's present in your copy of Strange, I have no explanaiton at all for your error. Sadly, this might have to wait for my return so that I can step through the code and see what's going wrong.
     
  14. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    No problem have a good end of holiday.
    My problem can wait your come back.
    Sorry to disturb you

    Thanks and strange still a superb plugin to play with and permit a lot of great things.
     
  15. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    BIG NEWS for StrangeIoC!

    The first Strange project to go LIVE (that we know of, anyway) is now available for you to check out!

    http://www.defeatkhan.com

    Strange is hardly the most interesting thing on site, as you'll see when you go there, but what a great project for a Strange debut!
     
  16. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    Hi srimarc

    I hope you had a great holiday !
    I still working on my project with strange IOC, i still have my problem with my load and unload context, i still have a "missing component exception" !
    I made somes research on the web to understand more the loadadditive feature, i'm not really familiate with that !
    I find this post that is interesting !

    http://answers.unity3d.com/questions/24251/loadleveladditive-requires-one-frame-to-initialize.html

    It talk about load additive and it seem to need one frame to initialize properly ! I will investigate on this today to understand if my problem could come from this mecanism.

    Thanks
     
  17. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    Hi picpic,

    First day back! Hope to look at this issue today. Will be in touch. :)
     
  18. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    Picpic,

    I've got good news and bad news...and they're really the same thing. I've completed tests that demonstrate to my satisfaction that Context removal works (good news for me and for Strange). I can't immediately explain, therefore, why you get the error you get (bad news for you). Very shortly I will push a small change to the example files, which will enable you to see and test Context removal for yourself, so you can see that it works. Maybe seeing it working will help you work out what you're doing differently.
     
  19. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    Commit dd0a42c now on master demonstrates proper removal of a Context. HTH!!!!
     
  20. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
  21. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    Hi,
    I just do a long test to see what is wrong, and i done an interresting discover !

    Before i made my unload automatiquely while it load the over context !
    Now i just create a button on my gui to unload my context before load the over and it work only i have just on context loaded if my menu context was load with my level01 context i have the bug

    but if i unload by clicking on the button my level01context and then i load my menu context by clicking on it all work good !

    I don'ty know with this is appen but it happen !

    this is my test
    https://docs.google.com/file/d/0B7tPUWigHdTGVktuQVlfLUh3T1k/edit?usp=sharing

    thanks

    I just have one question is it important to create namespace for use with strange to avoid conflict !
     
  22. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    HAHHHHAAA !!!

    I touch the solution by the really end of my little finger !!!!

    in my menu context i have this binded to remove my context !

    Code (csharp):
    1. commandBinder.Bind(Main_Event.REMOVELEVEL01CONTEXT).To<RemoveContextCommand>();
    and in my level 01 context i have the same line

    Code (csharp):
    1. commandBinder.Bind(Main_Event.REMOVELEVEL01CONTEXT).To<RemoveContextCommand>();
    if i map with a named injection in my level01

    Code (csharp):
    1. commandBinder.Bind(Main_Event.REMOVELEVEL01CONTEXT).To<RemoveContextCommand>().ToName("level01");
    it doesn't work any more for any context !

    So i think my type binding is a problem !
     
    Last edited: Sep 4, 2013
  23. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    Ok i have the solution !

    My mistake if is one ! was to set the same event "Main_Event.removecontext", to my menu context binding,

    and my level 01 binding !

    if i make a different event for my unload one for level01 one for menu, now in my unloadcommand i can remove the two context that was loaded by the gui button now i have to find a solution with my automatic unload !

    thanks
     
  24. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    Code (csharp):
    1.  
    So another test and i must admit that i'm completely lost !

    I made my loadsscene so in my main_start_command i dispatch my loadscene

    Code (csharp):
    1.  
    2. public override void Execute()
    3.     {
    4.         Debug.Log("main is start");
    5.         dispatcher.Dispatch(Main_Event.LOAD_SCENE, "Gui");
    6.        
    7.         dispatcher.Dispatch(Main_Event.LOAD_SCENE, "Level01");//load
    8.         dispatcher.Dispatch(Main_Event.LOAD_SCENE, "Menu");//load
    9.        
    10.         /*order of the remove context
    11.         //crosscontextdispatcher.Dispatch(Main_Event.REMOVEMENUCONTEXT);
    12.         //crosscontextdispatcher.Dispatch(Main_Event.REMOVELEVEL01CONTEXT);*/
    13.     }
    14.  
    in my gui i have my remove context button that dispatch via a gui command and a crosscontextdispatcher

    Code (csharp):
    1. public class Gui_RemoveContext : EventCommand
    2. {
    3.     [Inject(ContextKeys.CROSS_CONTEXT_DISPATCHER)]
    4.     public IEventDispatcher crosscontextdispatcher{get;set;}
    5.    
    6.     public override void Execute()
    7.     {
    8.         Debug.Log("remove level");
    9.         crosscontextdispatcher.Dispatch(Main_Event.REMOVEMENUCONTEXT);
    10.         crosscontextdispatcher.Dispatch(Main_Event.REMOVELEVEL01CONTEXT);
    11.     }
    12. }
    It WORRRRRRRRRRKKKK !!!!:-o

    Now i invert the order of the load scene in my main_start_command

    Code (csharp):
    1.  
    2. dispatcher.Dispatch(Main_Event.LOAD_SCENE, "Level01"); 
    3. dispatcher.Dispatch(Main_Event.LOAD_SCENE, "Menu");
    4.  
    And ban Error !!!:confused:

    if i inverse my remove dispatch ! it work again

    Code (csharp):
    1.  
    2. public override void Execute()
    3.     {
    4.         Debug.Log("remove level");
    5.        
    6.         crosscontextdispatcher.Dispatch(Main_Event.REMOVEMENUCONTEXT);
    7.         crosscontextdispatcher.Dispatch(Main_Event.REMOVELEVEL01CONTEXT);
    8.     }
    9.  
    the order of remove have to be exactly the inverse of my load !

    It seem that my load order is important in the way that my main context so first context stock the over context ?

    i'm really sorry but if you can take a eye of what i'm doing wrong in this really really simple test !

    https://docs.google.com/file/d/0B7tPUWigHdTGZnpFYTE1eTZLSkE/edit?usp=sharing

    Thanks !!!!
     
    Last edited: Sep 4, 2013
  25. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    Picpic,

    Strange absolutely doesn't care about the order in which you add and/or remove your contexts. It seems highly likely that the issue is somewhere in the rest of your code. I recommend you use MonoDevelop's debugging tools (breakpoints, stack traces, etc) to work it out. I want to be helpful, but there's only so far I can reasonably go in debugging your code. Best of luck!
     
  26. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    I agree with you but the thing is my code is empty i just load and unload empty scene !

    Of course if i wan't to only remove on context all work as your demo but my pupose is a little more complex because i wan't to switch between contexts.
    If strange propose multi context app it will be a standard use for it.

    I will debug my code !
     
  27. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    I agree. If you can demonstrate the problem in an abstract, repeatable test which you're reasonably sure you've gone over to eliminate the likelihood that the issue is in your own methodology, then of course I'm happy to help. :)

    When you reach that stage, let me know and I'll arrange to have you send me an archive of the whole project, so I can properly assess the problem.
     
  28. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    I'm really sorry to insist but it is exactly what i wan't to be be sure "Do i make the things right ?".

    If you take a eye at the archive you ll see that i just make a load of a context and a button to unload it ! that version work !

    https://docs.google.com/file/d/0B7tPUWigHdTGUW5DZk0zalpBVEU/edit?usp=sharing

    but if i load more than one context a the application start and try to remove it the same way as the first i have the bug !

    Please i don't say that strange have a bug i just wan't to know why my method isn't work to clarify !

    To see the bug you have just to uncomment one line !

    Code (csharp):
    1. public class Main_StartCommand : EventCommand
    2. {
    3.    
    4.     [Inject(ContextKeys.CONTEXT_VIEW)]
    5.     public GameObject contextView{get;set;}
    6.    
    7.     public override void Execute()
    8.     {
    9.         Debug.Log("main is start");
    10.        
    11.         dispatcher.Dispatch(Main_Event.LOAD_SCENE, "Gui");
    12.         dispatcher.Dispatch(Main_Event.LOAD_SCENE, "Menu");
    13.         //dispatcher.Dispatch(Main_Event.LOAD_SCENE, "Level01");//to uncomment to see the bug please
    14.        
    15.         /*order of the remove context
    16.         //crosscontextdispatcher.Dispatch(Main_Event.REMOVEMENUCONTEXT);
    17.         //crosscontextdispatcher.Dispatch(Main_Event.REMOVELEVEL01CONTEXT);*/
    18.     }
    19. }
    Thanks
     
  29. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    Please make the Google doc public so I can see it. I'll try and find some time to look into this, but I can't promise anything this week, as I have a long list of bugs and features to address following my absence.
     
  30. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
  31. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    OK...there is indeed a legitimate issue here which a bit of debugging exposed. Seems like removing the Context can destabilize the dispatcher. I've written a fix which will go live very shortly.
     
  32. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    Picpic,

    Commit 82620f4 now on master should address your issue. Please pull and let me know.
     
  33. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    Great thanks for your time.

    I will try this tomorow i not have my project at home to test it.
     
  34. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    I ve just test it and it work well, i can now remove more than one context.

    Thanks
     
  35. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    Hi srimarc It me your worst nightmare !!! :D

    Ok i implement this morning my little test to load and unload context to my big project that is really bigger !

    And guess what it didn't work !:confused:

    But i debug and see that i made one thing differently than the démo.

    i had this error.

    Code (csharp):
    1. InvalidOperationException: HashSet have been modified while it was iterated over
    2. System.Collections.Generic.HashSet`1+Enumerator[strange.extensions.dispatcher.api.ITriggerable].CheckState ()
    3. System.Collections.Generic.HashSet`1+Enumerator[strange.extensions.dispatcher.api.ITriggerable].MoveNext ()
    4. strange.extensions.dispatcher.eventdispatcher.impl.EventDispatcher.Dispatch (System.Object eventType, System.Object data) (at Assets/StrangeIoC/scripts/strange/extensions/dispatcher/eventdispatcher/impl/EventDispatcher.cs:105)
    So i try to debug this thing, and i discover what was wrong, but i really don't know why it work this way, perhaps you can tell me more !

    I try to explain you clearly

    for removing my context i map in witch context an event when it is trigger call a global command.

    ex:

    In my description context

    Code (csharp):
    1. commandBinder.Bind(Description_Event.REMOVEDESCRIPTIONCONTEXT).To<RemoveContextCommand>();
    in my use context

    Code (csharp):
    1. commandBinder.Bind(Use_Event.REMOVEUSECONTEXT).To<RemoveContextCommand>();
    in my main menu context

    Code (csharp):
    1. commandBinder.Bind(Main_Menu_Event.REMOVEMAINMENUCONTEXT).To<RemoveContextCommand>();
    and my command

    Code (csharp):
    1. using System;
    2. using strange.extensions.context.impl;
    3. using strange.extensions.command.impl;
    4. using strange.extensions.context.api;
    5. using UnityEngine;
    6.  
    7. public class RemoveContextCommand : EventCommand
    8. {
    9.     [Inject(ContextKeys.CONTEXT)]
    10.     public IContext context{get;set;}
    11.    
    12.     [Inject(ContextKeys.CONTEXT_VIEW)]
    13.     public GameObject contextView{get;set;}
    14.    
    15.     public override void Execute()
    16.     {
    17.         Debug.Log("remove : "+context);
    18.         Context.firstContext.RemoveContext(context);
    19.         GameObject.Destroy(contextView);
    20.     }
    21. }
    22.  
    when i start my appli my main menu is load when i click to load my use or my description it remove correctly main menu but, it tell me that error. If i comment the remove line in my command it work but don't remove the context.

    If i do a different command for eatch context

    Ex:

    Code (csharp):
    1. commandBinder.Bind(Description_Event.REMOVEDESCRIPTIONCONTEXT).To<Use_RemoveContextCommand>();
    it work very well it remove the context and his gameobject. All is fine.

    My question is :

    Is it a normal use, or perhaps i map the wronly way that is very possible. I will be possible to map a unique command to eatch context. My error is this time to in eventdispatcher.cs.

    Thanks you !
     
  36. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    Hi srimarc It me your worst nightmare !!! :D

    Ok i implement this morning my little test to load and unload context to my big project that is really bigger !

    And guess what it didn't work !:confused:

    But i debug and see that i made one thing differently than the démo.

    i had this error.

    Code (csharp):
    1. InvalidOperationException: HashSet have been modified while it was iterated over
    2. System.Collections.Generic.HashSet`1+Enumerator[strange.extensions.dispatcher.api.ITriggerable].CheckState ()
    3. System.Collections.Generic.HashSet`1+Enumerator[strange.extensions.dispatcher.api.ITriggerable].MoveNext ()
    4. strange.extensions.dispatcher.eventdispatcher.impl.EventDispatcher.Dispatch (System.Object eventType, System.Object data) (at Assets/StrangeIoC/scripts/strange/extensions/dispatcher/eventdispatcher/impl/EventDispatcher.cs:105)
    So i try to debug this thing, and i discover what was wrong, but i really don't know why it work this way, perhaps you can tell me more !

    I try to explain you clearly

    for removing my context i map in witch context an event when it is trigger call a global command.

    ex:

    In my description context

    Code (csharp):
    1. commandBinder.Bind(Description_Event.REMOVEDESCRIPTIONCONTEXT).To<RemoveContextCommand>();
    in my use context

    Code (csharp):
    1. commandBinder.Bind(Use_Event.REMOVEUSECONTEXT).To<RemoveContextCommand>();
    in my main menu context

    Code (csharp):
    1. commandBinder.Bind(Main_Menu_Event.REMOVEMAINMENUCONTEXT).To<RemoveContextCommand>();
    and my command

    Code (csharp):
    1. using System;
    2. using strange.extensions.context.impl;
    3. using strange.extensions.command.impl;
    4. using strange.extensions.context.api;
    5. using UnityEngine;
    6.  
    7. public class RemoveContextCommand : EventCommand
    8. {
    9.     [Inject(ContextKeys.CONTEXT)]
    10.     public IContext context{get;set;}
    11.    
    12.     [Inject(ContextKeys.CONTEXT_VIEW)]
    13.     public GameObject contextView{get;set;}
    14.    
    15.     public override void Execute()
    16.     {
    17.         Debug.Log("remove : "+context);
    18.         Context.firstContext.RemoveContext(context);
    19.         GameObject.Destroy(contextView);
    20.     }
    21. }
    22.  
    when i start my appli my main menu is load when i click to load my use or my description it remove correctly main menu but, it tell me that error. If i comment the remove line in my command it work but don't remove the context.

    If i do a different command for eatch context

    Ex:

    Code (csharp):
    1. commandBinder.Bind(Description_Event.REMOVEDESCRIPTIONCONTEXT).To<Description_RemoveContextCommand>();
    it work very well it remove the context and his gameobject. All is fine.

    My question is :

    Is it a normal use, or perhaps i map the wronly way that is very possible. I will be possible to map a unique command to eatch context. My error is this time to in eventdispatcher.cs.

    Thanks you !
     
  37. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    Hi
    same error in my test demo !

    Code (csharp):
    1. InvalidOperationException: HashSet have been modified while it was iterated over
    2. System.Collections.Generic.HashSet`1+Enumerator[strange.extensions.dispatcher.api.ITriggerable].CheckState ()
    3. System.Collections.Generic.HashSet`1+Enumerator[strange.extensions.dispatcher.api.ITriggerable].MoveNext ()
    4. strange.extensions.dispatcher.eventdispatcher.impl.EventDispatcher.Dispatch (System.Object eventType, System.Object data) (at Assets/StrangeIoC/scripts/strange/extensions/dispatcher/eventdispatcher/impl/EventDispatcher.cs:105)
    link

    https://docs.google.com/file/d/0B7tPUWigHdTGVzE5Mi0taXlJWjQ/edit?usp=sharing

    I made a debbug with a picture
    https://docs.google.com/file/d/0B7tPUWigHdTGR3BFWmhhYVNMUmc/edit?usp=sharing

    Thanks
     
    Last edited: Sep 5, 2013
  38. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    It appears to me that the problem you're seeing comes from adding and removing contexts in the same turn. I can probably armor against this better, but that isn't going to happen anytime soon. Try separating the calls. Load, then remove...or vice-versa.
     
  39. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    Ok thanks i will try that in a command in sequence or any think like that !
     
  40. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
  41. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    I just test to make my sequence command it's ok all work and i not any more missing reference exception.

    Thanks
     
  42. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    There's a new branch on #StrangeIoC: SIGNALS! We won't roll this into master for at least a few days (so treat it as experimental), and docs are forthcoming, but I encourage you to start signaling.

    https://github.com/thirdmotion/strangeioc/tree/signals

    This will be release 0.6.0. It also includes improvements to CrossContext mapping.

    Kudos to contributor Will Corwin for the implementation!
     
  43. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    The signals branch is now code-complete, tested and documented. We encourage our users to take it for a spin and test it out. If all goes well, we'll roll it onto the master branch at the end of this week.

    https://github.com/thirdmotion/strangeioc/tree/signals

    Features:
    - Signals: a new, type-safe dispatch system modeled on AS3Signals/QTSignals
    - New CrossContext injector makes sharing mappings between contexts trivial (Signals are fully cross-context compatible)
    - Bug fixes
     
  44. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    We just pushed a couple of fixes to the StrangeIoC signals branch, plus we added a big improvement to how you dispatch events cross-context. All gets rolled into master TOMORROW!

    http://bit.ly/19quE9c
     
  45. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    Today's my birthday. The present is for you:

    StrangeSignals is now on master!
    https://github.com/thirdmotion/strangeioc

    This is a VERY IMPORTANT update for Strange, including signals, important cross-context improvements, lots of bug fixes. Get it now!

    AND, we're now blessing strange-core as official!
    https://github.com/thirdmotion/strange-core
    Strange-core is just the code, minus examples, etc. It's the best way for pro users of Strange to integrate it in-project as a submodule.
     
  46. OrekaIngenierie

    OrekaIngenierie

    Joined:
    Jul 6, 2012
    Posts:
    67
    Happy birthday !
     
  47. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
  48. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
    So a weekend with Tumblr has convinced me that putting our blog there was a mistake. Moving to WordPress.

    https://strangeioc.wordpress.com

    (Apologies for any inconvenience)
     
  49. srimarc

    srimarc

    Joined:
    Nov 1, 2012
    Posts:
    86
  50. EmeralLotus

    EmeralLotus

    Joined:
    Aug 10, 2012
    Posts:
    1,462
    This is really Fantastic work.

    Does the framework work for all Unity platforms... Web, Desktop, Mobile (IOS,Android, win8,blackberry) ?

    Thanks.