• WorldWind学习系列五:插件加载过程全解析


      不得不承认World Wind的代码真的很庞大,没有太多帮助文档的前提下,一头钻进代码里肯定令你头疼的,甚至研究代码间关联仿佛是在走迷宫。我最近一直想弄明白如何在MenuBar中加载那些插件的,WorldWind学习系列四中研究的只是特殊的三个功能加载的,那三个没有继承Plugin类,不算是插件功能加载。所以WorldWind学习系列四加载的三个是特殊情况,不是一般的插件加载。今天下午终于柳暗花明,如果你真正关注World Wind分析,那么就好好看看下面的插件加载过程全解析。

          我们先看看Plugin类的继承图,看看到底都有些什么插件,然后在分析一般性的插件加载全过程。

    插件类继承关系图
      哦,原来这么多插件,我们要基于WW开发自己的应用,只需继承Plugin类写出自己的插件功能即可的。
         我们现在分析插件加载过程,请确保你看过WorldWind学习系列二:擒贼先擒王篇2 中的(5.加载上次使用的配置信息)。加载的插件入口就是WorldWind.cs的Main()中调用的LoadSettings()静态方法。
      1.读取WorldWind的配置中插件信息
    加载WorldWind配置
    private static void LoadSettings()
            {
                
    try
                {
        //先读取上次使用时保存的“使用插件配置文件”,如果存在,则从文件中读取配置实例化WorldWindSettings
                    Settings 
    = (WorldWindSettings) SettingsBase.Load(Settings, SettingsBase.LocationType.User);

                    
    if(!File.Exists(Settings.FileName))
                    {
               //我们假定是配置文件不存在,这就是一个个地加载插件,保存到ArrayList中 
                        Settings.PluginsLoadedOnStartup.Add(
    "ShapeFileInfoTool");
                        
    //Settings.PluginsLoadedOnStartup.Add("OverviewFormLoader");
                        
    //Settings.PluginsLoadedOnStartup.Add("Atmosphere");
                        Settings.PluginsLoadedOnStartup.Add("SkyGradient");
                        Settings.PluginsLoadedOnStartup.Add(
    "BmngLoader");
                        
    //Settings.PluginsLoadedOnStartup.Add("Compass");
                        
    //Settings.PluginsLoadedOnStartup.Add("ExternalLayerManagerLoader");
                        Settings.PluginsLoadedOnStartup.Add("MeasureTool");
                        
    //Settings.PluginsLoadedOnStartup.Add("MovieRecorder");
                        Settings.PluginsLoadedOnStartup.Add("NRLWeatherLoader");
                        Settings.PluginsLoadedOnStartup.Add(
    "ShapeFileLoader");
                        Settings.PluginsLoadedOnStartup.Add(
    "Stars3D");
                        Settings.PluginsLoadedOnStartup.Add(
    "GlobalClouds");
                        Settings.PluginsLoadedOnStartup.Add(
    "PlaceFinderLoader");
                        Settings.PluginsLoadedOnStartup.Add(
    "LightController");

                        Settings.PluginsLoadedOnStartup.Add(
    "Earthquake_2.0.2.1");
                        Settings.PluginsLoadedOnStartup.Add(
    "Historical_Earthquake_2.0.2.2");
                        Settings.PluginsLoadedOnStartup.Add(
    "KMLImporter");
                        
    //Settings.PluginsLoadedOnStartup.Add("doublezoom");
                        
    //Settings.PluginsLoadedOnStartup.Add("PlanetaryRings");
                        Settings.PluginsLoadedOnStartup.Add("TimeController");
                        
    //Settings.PluginsLoadedOnStartup.Add("WavingFlags");
                        Settings.PluginsLoadedOnStartup.Add("ScaleBarLegend");
                        Settings.PluginsLoadedOnStartup.Add(
    "Compass3D");
                        Settings.PluginsLoadedOnStartup.Add(
    "AnaglyphStereo");
                        Settings.PluginsLoadedOnStartup.Add(
    "GlobeIcon");

                    }
                    
    // decrypt encoded user credentials
                    DataProtector dp = new DataProtector(DataProtector.Store.USE_USER_STORE);

                    
    if(Settings.ProxyUsername.Length > 0) Settings.ProxyUsername = dp.TransparentDecrypt(Settings.ProxyUsername);
                    
    if(Settings.ProxyPassword.Length > 0) Settings.ProxyPassword = dp.TransparentDecrypt(Settings.ProxyPassword);
                }
                
    catch(Exception caught)
                {
                    Log.Write(caught);
                }
            }

      2.Main()中后面调用MainApplication()方法,该MainApplication()调用OpenStartupWorld(),用来初始化启动World对象。OpenStartupWorld()方法首先确定加载的是Earth/Moon等,然后开始加载一个星球。

    加载一个星球代码
            /// <summary>
            
    /// Loads a new planet
            
    /// </summary>
            private void OpenWorld(string worldXmlFile)
            {
                
                
    if(this.worldWindow.CurrentWorld != null)
                {
                    
    try
                    {
                        
    this.worldWindow.ResetToolbar();
                    }
                    
    catch
                    {}

                    
    try
                    {
                        
    foreach(PluginInfo p in this.compiler.Plugins)
                        {
                            
    try
                            {
                                
    if(p.Plugin.IsLoaded)
                                    p.Plugin.Unload();
                            }
                            
    catch
                            {}
                        }
                    }
                    
    catch
                    {}
                    
                    
    try
                    {
                        
    this.worldWindow.CurrentWorld.Dispose();
                    }
                    
    catch
                    {}
                    
                }


                
    if(this.gotoDialog != null)
                {
                    
    this.gotoDialog.Dispose();
                    
    this.gotoDialog = null;
                }

                
    if(this.rapidFireModisManager != null)
                {
                    
    this.rapidFireModisManager.Dispose();
                    
    this.rapidFireModisManager = null;
                }

                
    if(this.animatedEarthMananger != null)
                {
                    
    this.animatedEarthMananger.Dispose();
                    
    this.animatedEarthMananger = null;
                }

                
    if(this.wmsBrowser != null)
                {
                    
    this.wmsBrowser.Dispose();
                    
    this.wmsBrowser = null;
                }

                worldWindow.CurrentWorld 
    = WorldWind.ConfigurationLoader.Load(worldXmlFile, worldWindow.Cache);
         
           this.splashScreen.SetText("Initializing menus...");
                // InitializePluginCompiler()是我们要关注的初始化插件编辑器PluginCompiler(真正管理加载插件的类)
                
    InitializePluginCompiler();
           
           //RenderableObject系统很复杂,我们稍后准备专门分析一下
                
    foreach(RenderableObject worldRootObject in this.worldWindow.CurrentWorld.RenderableObjects.ChildObjects)
                {
                    
    this.AddLayerMenuButtons(this.worldWindow, worldRootObject);
                }
             
       //加载Earth专有的MenuButton( AnimatedEarthManager和RapidFireModisManager)的配置,
                //这里主要不关注
                
    this.AddInternalPluginMenuButtons();

                
    this.menuItemModisHotSpots.Enabled = worldWindow.CurrentWorld.IsEarth;
                
    this.menuItemAnimatedEarth.Enabled = worldWindow.CurrentWorld.IsEarth;
            }

      3.我们看看InitializePluginCompiler()如何加载插件的?

    初始化PluginCompiler
            /// <summary>
            
    /// Compile and run plug-in "scripts"
            
    /// </summary>
            private void InitializePluginCompiler()
            {
                Log.Write(Log.Levels.Debug, 
    "CONF""initializing plugin compiler...");
                
    this.splashScreen.SetText("Initializing plugins...");
                
    string pluginRoot = Path.Combine(DirectoryPath, "Plugins");
                compiler 
    = new PluginCompiler(this, pluginRoot);

    //#if DEBUG
                
    // Search for plugins in worldwind.exe (plugin development/debugging aid)
                compiler.FindPlugins(Assembly.GetExecutingAssembly());
    //#endif
           //从启动文件夹下Plugins文件夹,加载插件
                compiler.FindPlugins();
          //加载启动插件插件
                
    compiler.LoadStartupPlugins();
            }

      4.加载启动插件函数的代码

    加载启动插件
    /// Loads the plugins that are set for load on world wind startup.
            
    /// </summary>
            public void LoadStartupPlugins()
            {
                
    foreach(PluginInfo pi in m_plugins)
                {
                    
    if(pi.IsLoadedAtStartup)
                    {
                        
    try
                        {
                            
    // Compile
                            Log.Write(Log.Levels.Debug, LogCategory, "loading "+pi.Name+" ...");
                            worldWind.SplashScreen.SetText(
    "Initializing plugin " + pi.Name);
         //Load()方法加载插件,Plugin类的Load()为虚方法,实质上调用的是各个插件重载后的Load()方法
                            
    Load(pi);
                        }
                        
    catch(Exception caught)
                        {
                            
    // Plugin failed to load
                            string message = "Plugin " + pi.Name + " failed: " + caught.Message;
                            Log.Write(Log.Levels.Error, LogCategory, message);
                            Log.Write(caught);

                            
    // Disable automatic load of this plugin on startup
                            pi.IsLoadedAtStartup = false;

                            worldWind.SplashScreen.SetError(message);
                        }
                    }
                }
            }

      5.现在看两个插件类重载的Load()方法的实例。例如:Compass3D.cs和TimeController.cs。

      Compass3D.cs的Load()方法

    重载后的Load方法
     21行     public override void Load()
            {
                m_menuItem 
    = new System.Windows.Forms.MenuItem("Compass");
                m_menuItem.Click 
    += new EventHandler(m_menuItem_Click);
                m_menuItem.Checked 
    = World.Settings.ShowCompass;
                ParentApplication.ToolsMenu.MenuItems.Add(m_menuItem);
                
                m_form 
    = new FormWidget("Compass");
                m_form.ClientSize 
    = new System.Drawing.Size(200200);
                m_form.Location 
    = new System.Drawing.Point(0400);
                m_form.BackgroundColor 
    = World.Settings.WidgetBackgroundColor;
                m_form.AutoHideHeader 
    = true;
                m_form.VerticalScrollbarEnabled 
    = false;
                m_form.HorizontalScrollbarEnabled 
    = false;
                m_form.BorderEnabled 
    = false;
          
     //注册两个窗体事件
                m_form.OnResizeEvent += new FormWidget.ResizeHandler(m_form_OnResizeEvent);
                m_form.OnVisibleChanged += new VisibleChangedHandler(m_form_OnVisibleChanged);
                //实例化Compass3DWidget
                m_compass 
    = new Compass3DWidget();
                m_compass.Location 
    = new System.Drawing.Point(50);
                m_compass.Font 
    = new System.Drawing.Font("Ariel"10.0f, System.Drawing.FontStyle.Bold);
                m_compass.ParentWidget 
    = m_form;
                m_form_OnResizeEvent(m_form, m_form.WidgetSize);
                
                m_form.ChildWidgets.Add(m_compass);
                m_form.Visible 
    = World.Settings.ShowCompass;
    //将要绘制的Widget加载到DrawArgs.NewRootWidget.ChildWidgets,为了在WorldWindow.cs的Render()方法里渲染
                DrawArgs.NewRootWidget.ChildWidgets.Add(m_form);
           
    //Compass 3D工具菜单按钮
                m_toolbarItem 
    = new WorldWind.NewWidgets.WidgetMenuButton(
                        
    "Compass 3D",
                        basePath 
    + "\\Data\\Icons\\Interface\\compass2.png",
                        m_form);
          
    //向MenuBar中添加Compass 3D菜单按钮
                
    ParentApplication.WorldWindow.MenuBar.AddToolsMenuButton(m_toolbarItem);
                
    base.Load();
            }

      TimeController.cs的Load方法,如下:

    TimeController.cs的Load方法
    时间控制
    public override void Load()
            {
                
    try
                {
                    m_window 
    = new WorldWind.NewWidgets.FormWidget("Time Control");
                    m_window.Name 
    = "Time Control";
                    m_window.ClientSize 
    = new System.Drawing.Size(300183);

                    
    // Bug in FormWidget required anchor to be set before Location and parent widget
                    m_window.Anchor = WorldWind.NewWidgets.WidgetEnums.AnchorStyles.Left | WorldWind.NewWidgets.WidgetEnums.AnchorStyles.Bottom;
                    m_window.ParentWidget 
    = DrawArgs.NewRootWidget;
                    m_window.Location 
    = new System.Drawing.Point(0, DrawArgs.NewRootWidget.ClientSize.Height - 183);
                    m_window.Text 
    = "Double Click to Re-Open";
                    m_window.BorderEnabled 
    = false;
                    m_window.AutoHideHeader 
    = true;
                    m_window.BackgroundColor 
    = System.Drawing.Color.FromArgb(0000);
                    m_window.HeaderEnabled 
    = true;
                    m_window.Visible 
    = false;

                    time 
    = new WorldWind.NewWidgets.PictureBox();
                    time.Name 
    = "Time";
                    time.ImageUri 
    = basePath + "\\Data\\Icons\\Time\\time off.png";
                    time.ClientLocation 
    = new System.Drawing.Point(1259);
                    time.ClientSize 
    = new System.Drawing.Size(4242);
                    time.Visible 
    = true;
                    time.ParentWidget 
    = m_window;
                    time.OnMouseEnterEvent 
    += new EventHandler(time_OnMouseEnterEvent);
                    time.OnMouseLeaveEvent 
    += new EventHandler(time_OnMouseLeaveEvent);
                    time.OnMouseUpEvent 
    += new MouseEventHandler(time_OnMouseUpEvent);
                    time.CountHeight 
    = false;
                    time.CountWidth 
    = true;
                    m_window.ChildWidgets.Add(time);

                    play 
    = new WorldWind.NewWidgets.PictureBox();
                    play.Name 
    = "Play";
                    
    if (TimeKeeper.Enabled)
                    {
                        play.ImageUri 
    = basePath + "\\Data\\Icons\\Time\\play on.png";
                    }
                    
    else
                    {
                        play.ImageUri 
    = basePath + "\\Data\\Icons\\Time\\play off.png";
                    }
                    play.ClientLocation 
    = new System.Drawing.Point(501);
                    play.ClientSize 
    = new System.Drawing.Size(8282);
                    play.Visible 
    = true;
                    play.ParentWidget 
    = m_window;
                    play.OnMouseEnterEvent 
    += new EventHandler(play_OnMouseEnterEvent);
                    play.OnMouseLeaveEvent 
    += new EventHandler(play_OnMouseLeaveEvent);
                    play.OnMouseUpEvent 
    += new System.Windows.Forms.MouseEventHandler(play_OnMouseUpEvent);
                    play.CountHeight 
    = true;
                    play.CountWidth 
    = true;
                    m_window.ChildWidgets.Add(play);

                    close 
    = new WorldWind.NewWidgets.PictureBox();
                    close.Name 
    = "Close";
                    close.ImageUri 
    = basePath + "\\Data\\Icons\\Time\\close off.png";
                    close.ClientLocation 
    = new System.Drawing.Point(293);
                    close.ClientSize 
    = new System.Drawing.Size(2222);
                    close.Visible 
    = true;
                    close.ParentWidget 
    = m_window;
                    close.OnMouseEnterEvent 
    += new EventHandler(close_OnMouseEnterEvent);
                    close.OnMouseLeaveEvent 
    += new EventHandler(close_OnMouseLeaveEvent);
                    close.OnMouseUpEvent 
    += new MouseEventHandler(close_OnMouseUpEvent);
                    close.CountHeight 
    = false;
                    close.CountWidth 
    = false;
                    m_window.ChildWidgets.Add(close);

                    rewind 
    = new WorldWind.NewWidgets.PictureBox();
                    rewind.Name 
    = "Rewind";
                    rewind.ImageUri 
    = basePath + "\\Data\\Icons\\Time\\repeat off.png";
                    rewind.ClientLocation 
    = new System.Drawing.Point(1626);
                    rewind.ClientSize 
    = new System.Drawing.Size(3232);
                    rewind.Visible 
    = true;
                    rewind.ParentWidget 
    = m_window;
                    rewind.OnMouseEnterEvent 
    += new EventHandler(rewind_OnMouseEnterEvent);
                    rewind.OnMouseLeaveEvent 
    += new EventHandler(rewind_OnMouseLeaveEvent);
                    rewind.OnMouseUpEvent 
    += new MouseEventHandler(rewind_OnMouseUpEvent);
                    rewind.CountHeight 
    = false;
                    rewind.CountWidth 
    = false;
                    m_window.ChildWidgets.Add(rewind);

                    pause 
    = new WorldWind.NewWidgets.PictureBox();
                    pause.Name 
    = "Pause";
                    
    if (TimeKeeper.Enabled)
                    {
                        pause.ImageUri 
    = basePath + "\\Data\\Icons\\Time\\pause off.png";
                    }
                    
    else
                    {
                        pause.ImageUri 
    = basePath + "\\Data\\Icons\\Time\\pause on.png";
                    }
                    pause.ClientLocation 
    = new System.Drawing.Point(3588);
                    pause.ClientSize 
    = new System.Drawing.Size(6464);
                    pause.Visible 
    = true;
                    pause.ParentWidget 
    = m_window;
                    pause.OnMouseEnterEvent 
    += new EventHandler(pause_OnMouseEnterEvent);
                    pause.OnMouseLeaveEvent 
    += new EventHandler(pause_OnMouseLeaveEvent);
                    pause.OnMouseUpEvent 
    += new System.Windows.Forms.MouseEventHandler(pause_OnMouseUpEvent);
                    pause.CountHeight 
    = true;
                    pause.CountWidth 
    = false;
                    m_window.ChildWidgets.Add(pause);

                    slow 
    = new WorldWind.NewWidgets.PictureBox();
                    slow.Name 
    = "Slow";
                    slow.ImageUri 
    = basePath + "\\Data\\Icons\\Time\\slow off.png";
                    slow.ClientLocation 
    = new System.Drawing.Point(9788);
                    slow.ClientSize 
    = new System.Drawing.Size(6464);
                    slow.Visible 
    = true;
                    slow.ParentWidget 
    = m_window;
                    slow.OnMouseEnterEvent 
    += new EventHandler(slow_OnMouseEnterEvent);
                    slow.OnMouseLeaveEvent 
    += new EventHandler(slow_OnMouseLeaveEvent);
                    slow.OnMouseUpEvent 
    += new System.Windows.Forms.MouseEventHandler(slow_OnMouseUpEvent);
                    slow.CountHeight 
    = false;
                    slow.CountWidth 
    = false;
                    m_window.ChildWidgets.Add(slow);

                    fast 
    = new WorldWind.NewWidgets.PictureBox();
                    fast.Name 
    = "Fast";
                    fast.ImageUri 
    = basePath + "\\Data\\Icons\\Time\\fast off.png";
                    fast.ClientLocation 
    = new System.Drawing.Point(15888);
                    fast.ClientSize 
    = new System.Drawing.Size(6464);
                    fast.Visible 
    = true;
                    fast.ParentWidget 
    = m_window;
                    fast.OnMouseEnterEvent 
    += new EventHandler(fast_OnMouseEnterEvent);
                    fast.OnMouseLeaveEvent 
    += new EventHandler(fast_OnMouseLeaveEvent);
                    fast.OnMouseUpEvent 
    += new System.Windows.Forms.MouseEventHandler(fast_OnMouseUpEvent);
                    fast.CountHeight 
    = false;
                    fast.CountWidth 
    = false;
                    m_window.ChildWidgets.Add(fast);

                    timeLabel 
    = new WorldWind.NewWidgets.TextLabel();
                    timeLabel.Name 
    = "Current Time";
                    timeLabel.ClientLocation 
    = new System.Drawing.Point(13465);
                    timeLabel.ClientSize 
    = new System.Drawing.Size(14060);
                    timeLabel.Visible 
    = true;
                    timeLabel.ParentWidget 
    = m_window;
                    timeLabel.Text 
    = GetCurrentTimeString();
                    TimeKeeper.Elapsed 
    += new System.Timers.ElapsedEventHandler(TimeKeeper_Elapsed);
                    timeLabel.CountHeight 
    = false;
                    timeLabel.CountWidth 
    = true;
                    timeLabel.WordBreak 
    = true;
                    m_window.ChildWidgets.Add(timeLabel);

                    DrawArgs.NewRootWidget.ChildWidgets.Add(m_window);

                    m_toolbarItem = new WorldWind.NewWidgets.WidgetMenuButton(
                        
    "Time Controller",
                        basePath + "\\Data\\Icons\\Time\\time off.png",
                        m_window);
          //向MenuBar中添加菜单按钮
                    ParentApplication.WorldWindow.MenuBar.AddToolsMenuButton(m_toolbarItem);
                }
                
    catch (Exception ex)
                {
                    Log.Write(ex);
                }
                
    base.Load();
            }

    其他插件的重载后的Load()方法也是类似的,不再赘述。希望能帮研究WW的朋友理清插件加载过程的思路,少走弯路。

    其他部分:

    WorldWind学习系列四:功能分析——Show Planet Axis、Show Position 、Show Cross Hairs功能

    WorldWind学习系列三:简单功能分析——主窗体的键盘监听处理及拷贝和粘贴位置坐标功能

    WorldWind学习系列三:功能分析——截屏功能和“关于”窗体分析

    WorldWind学习系列二:擒贼先擒王篇2

    WorldWind学习系列二:擒贼先擒王篇1

    WorldWind学习系列一:顺利起航篇


     

       

  • 相关阅读:
    【STM32F429】第4章 RTX5操作系统移植(MDK AC5)
    【STM32F407】第4章 RTX5操作系统移植(MDK AC5)
    【STM32H7】第3章 RTX5操作系统介绍
    【STM32F429】第3章 RTX5操作系统介绍
    【STM32F407】第3章 RTX5操作系统介绍
    【STM32H7】第2章 初学RTX5准备工作
    【STM32F429】第2章 初学RTX5准备工作
    Hystrix解析(一)
    Eureka源码解析(五)
    Eureka源码分析(四)
  • 原文地址:https://www.cnblogs.com/wuhenke/p/1623078.html
Copyright © 2020-2023  润新知