Nebula2探秘15-Simple Application Framework

news/2024/7/8 4:28:40

 Nebula2探秘15-Simple Application  Framework

happykevins文 

         在经历了前14章的学习之后,本章将介绍一个简单的Nebula2应用程序框架nAppFrame。 nAppFrame可以说是nApplication的最简化版本,去掉了状态机和所有不必要的Packages和Servers。 nAppFrame的代码简单明了,易于使用,可以是省去每次重新创建Nebula2程序繁杂而枯燥的活动。
          以下的示例代码就应用了nAppFrame,并挂载了Render2D和Render3D两个函数,Render3D什么 事情都没做,读者有兴趣的话可以扩展该例子代码,例如显示个3D模型或骨骼动画之类的东东, 当然这些内容我将在以后章节中介绍,请大家继续关注Nebula2探秘哦:)

开始贴代码,nAppFrame的代码:

/* ************************************************************************** */
/*     Nebula2 - Tutorial nAppFrame                                             */
/*   A Simple Program Framework                                                 */
/*   author: happykevins                                                         */
/* ************************************************************************** */
#pragma  once

//  关闭讨厌的类型检查warning
#pragma  warning(disable: 4244 4267)

#include 
" kernel/nkernelserver.h "
#include 
" kernel/nroot.h "
#include 
" kernel/nautoref.h "
#include 
" gfx2/ndisplaymode2.h "
#include 
" gfx2/ncamera2.h "
#include 
" tools/nmayacamcontrol.h "
#include 
" tools/nnodelist.h "

class  nScriptServer;
class  nGfxServer2;
class  nInputServer;
class  nConServer;
class  nResourceServer;
class  nSceneServer;
class  nVariableServer;
class  nAnimationServer;
class  nParticleServer;
class  nVideoServer;
class  nGuiServer;
class  nShadowServer2;
class  nAudioServer3;
class  nPrefServer;
class  nLocaleServer;

//  
//  class nAppFrame
//  仿照napplication制作的一个Nebula2应用程序框架,对初始化和运行做了减化
//  只开启我认为必要的服务
//
class  nAppFrame :  public  nRoot
{
public :
    typedef 
void  ( * nFunc) ( void );

    nAppFrame();
    
~ nAppFrame();
    
    
///  初始化Nebula2引擎
     bool  OpenNebula();
    
///  关闭Nebula2引擎
     bool  CloseNebula();
    
///  进入Nebula2引擎的主循环
     void  RunNebula();

    
///  用户可重载的初始化方法(在OpenNebula的最后被调用)
     virtual   bool  ClientOpen() { return   true ;}
    
///  用户可重载的关闭方法(在CloseNebula之前被调用)
     virtual   bool  ClientClose() { return   true ;}

    
///  在这里添加3D渲染代码
     virtual   void  OnRender3D();
    
///  在这里添加2D渲染代码
     virtual   void  OnRender2D();
    
///  在这里添加游戏逻辑代码
     virtual   void  OnFrame();

    
///  Kernel Server
     static  nKernelServer *  ks;

    
///  OnFrame Function Hook
    nFunc m_fpOnFrame;
    
///  OnRender3D Function Hook
    nFunc m_fpOnRender3D;
    
///  OnRender2D Function Hook
    nFunc m_fpOnRender2D;

    
///  nNode节点列表
    nNodeList m_nodes;

protected :

    
///  摄像机控制代码(有默认实现,用户可重载)
     virtual   void  OnCameraControll();

    
///  Nebula2启动标志
     bool  isOpen;

    
///  Servers
    nAutoRef < nScriptServer >      refScriptServer;
    nAutoRef
< nGfxServer2 >        refGfxServer;
    nAutoRef
< nInputServer >       refInputServer;
    nAutoRef
< nConServer >         refConServer;
    nAutoRef
< nResourceServer >    refResourceServer;
    nAutoRef
< nSceneServer >       refSceneServer;
    nAutoRef
< nVariableServer >    refVariableServer;
    nAutoRef
< nGuiServer >         refGuiServer;
    nAutoRef
< nShadowServer2 >     refShadowServer;
    nAutoRef
< nParticleServer >    refParticleServer;
    nAutoRef
< nAnimationServer >   refAnimationServer;

    
// nAutoRef       refVideoServer;
    
// nAutoRef      refAudioServer;
    
// nAutoRef        refPrefServer;
    
// nAutoRef      refLocaleServer;

    
///  Camera Controll
    nDisplayMode2 display;
    nCamera2 camera;
    matrix44 view;
    nMayaCamControl m_ccam;
};
///  nappframe.cpp

#include 
" nappframe.h "
#include 
" nutildefs.h "

#include 
" kernel/nfileserver2.h "
#include 
" kernel/ntimeserver.h "
#include 
" kernel/nscriptserver.h "
#include 
" gfx2/ngfxserver2.h "
#include 
" input/ninputserver.h "
#include 
" misc/nconserver.h "
#include 
" resource/nresourceserver.h "
#include 
" scene/nsceneserver.h "
#include 
" variable/nvariableserver.h "
#include 
" anim2/nanimationserver.h "
#include 
" particle/nparticleserver.h "
#include 
" video/nvideoserver.h "
#include 
" gui/nguiserver.h "
#include 
" kernel/nremoteserver.h "
#include 
" audio3/naudioserver3.h "
#include 
" misc/nprefserver.h "
#include 
" locale/nlocaleserver.h "
#include 
" shadow2/nshadowserver2.h "

nNebulaUsePackage(nnebula);
nNebulaUsePackage(ntoollib);
nNebulaUsePackage(ndirect3d9);
nNebulaUsePackage(ndinput8);
nNebulaUsePackage(ngui);

nNebulaScriptModule(nAppFrame, nappframe, 
" nroot " );

void  nNebulaScriptInitCmds(nappframe)(nClass  * )
{
    
///  add any cmd you want.
}

nKernelServer
*  nAppFrame::ks  =  NULL;

nAppFrame::nAppFrame() :
    isOpen(
false ),
    refScriptServer(
" /sys/servers/script " ),
    refGfxServer(
" /sys/servers/gfx " ),
    refInputServer(
" /sys/servers/input " ),
    refConServer(
" /sys/servers/console " ),
    refResourceServer(
" /sys/servers/resource " ),
    refSceneServer(
" /sys/servers/scene " ),
    refVariableServer(
" /sys/servers/variable " ),
    refGuiServer(
" /sys/servers/gui " ),
    refShadowServer(
" /sys/servers/shadow " ),
    refParticleServer(
" /sys/servers/particle " ),
    refAnimationServer(
" /sys/servers/anim " )

    
// refVideoServer("/sys/servers/video"),
    
// refAudioServer("/sys/servers/audio"),
    
// refPrefServer("/sys/servers/nwin32prefserver"),
    
// refLocaleServer("/sys/servers/locale"),
{
    n_assert(
! nAppFrame::ks);

    nAppFrame::ks 
=  n_new(nKernelServer);

    m_fpOnFrame        
=  NULL;
    m_fpOnRender3D    
=  NULL;
    m_fpOnRender2D    
=  NULL;
}

nAppFrame::
~ nAppFrame()
{
    n_assert(nAppFrame::ks);

    n_delete(nAppFrame::ks);
    nAppFrame::ks 
=  NULL;
}

///  Open Nebula App
bool  nAppFrame::OpenNebula()
{
    
///  Add Modules
    ks -> AddPackage(nnebula);
    ks
-> AddPackage(ntoollib);
    ks
-> AddPackage(ndirect3d9);
    ks
-> AddPackage(ndinput8);
    ks
-> AddPackage(ngui);

    
///  Create Servers
    ks -> New( " ntclserver " ,         " /sys/servers/script " );
    ks
-> New( " nresourceserver " ,     " /sys/servers/resource " );
    ks
-> New( " nvariableserver " ,     " /sys/servers/variable " );
    ks
-> New( " ndi8server " ,         " /sys/servers/input " );
    ks
-> New( " nguiserver " ,         " /sys/servers/gui " );
    ks
-> New( " nconserver " ,         " /sys/servers/console " );
    ks
-> New( " nd3d9server " ,         " /sys/servers/gfx " );
    ks
-> New( " nsceneserver " ,         " /sys/servers/scene " );
    ks
-> New( " nshadowserver2 " ,     " /sys/servers/shadow " );
    ks
-> New( " nparticleserver " ,     " /sys/servers/particle " );
    ks
-> New( " nanimationserver " " /sys/servers/anim " );

    
// ks->New("ndshowserver", "/sys/servers/video");
    
// ks->New("nprefserver", "/sys/servers/nwin32prefserver");
    
// ks->New("nlocaleserver", "/sys/servers/locale");
    
// ks->New("ndsoundserver3", "/sys/servers/audio");

    
///  SetDisplay
    display.SetXPos( 150 );
    display.SetYPos(
100 );
    display.SetWidth(
640 );
    display.SetHeight(
480 );
    refGfxServer
-> SetDisplayMode(display);
    refGfxServer
-> SetCamera(camera);

    
///
    nString ret;

    
///  获得FileServer设置系统路径
    nFileServer2 *  file  =  (nFileServer2 * )ks -> Lookup( " sys/servers/file2 " );
    
///  设置系统路径
    file -> SetAssign( " home " ,             " bin:../../ " );
    file
-> SetAssign( " renderpath " ,     " home:datafiles/shaders " );
    file
-> SetAssign( " scripts " ,         " home:datafiles/scripts " );

    file
-> SetAssign( " particles " ,     " home:datafiles/particles " );
    file
-> SetAssign( " gfxlib " ,         " home:datafiles/gfxlib " );
    file
-> SetAssign( " textures " ,         " home:datafiles/textures " );
    file
-> SetAssign( " meshes " ,         " home:datafiles/meshes " );
    file
-> SetAssign( " anims " ,         " home:datafiles/anims " );

    
///  启动RemoteServer
    ks -> GetRemoteServer() -> Open( " 8379 " );

    
///  启动sceneserver(启动d3d9server)
    refSceneServer -> SetRenderPathFilename( " renderpath:dx7_renderpath.xml " );
    
if  (  ! refSceneServer -> Open() )
    {
        
return   false ;
    }

    
///  启动GUIServer
    ret.Clear();
    refScriptServer
-> RunScript( " scripts:ngui.tcl " , ret);
    refGuiServer
-> Open();

    
///  Map Input
    refInputServer -> Open();
    ret.Clear();
    refScriptServer
-> RunScript( " scripts:ninput.tcl " , ret);

    
///  Open node list
     this -> m_nodes.SetStageScript( " gfxlib:stdlight.n2 " );
    
this -> m_nodes.Open();

    
///  Init Client Res
     this -> ClientOpen();

    
///  make the open mark
     this -> isOpen  =   true ;

    
return   true ;
}

///  Close Nebula App
bool  nAppFrame::CloseNebula()
{
    
///  make the close mark
     this -> isOpen  =   false ;

    
///  release client res
     this -> ClientClose();

    
///  close node list
     this -> m_nodes.Close();

    
///  close servers
     if  ( this -> refGuiServer.isvalid())
    {
        
this -> refGuiServer -> Close();
    }
    
if  ( this -> refSceneServer.isvalid())
    {
        
this -> refSceneServer -> Close();
    }
    
// if (this->refAudioServer.isvalid())
    
// {
    
//     this->refAudioServer->Close();
    
// }
    
// if (this->refVideoServer.isvalid())
    
// {
    
//     this->refVideoServer->Close();
    
// }
    
// if (this->refLocaleServer.isvalid())
    
// {
    
//     if (this->refLocaleServer->IsOpen())
    
//         this->refLocaleServer->Close();
    
// }

    
//  close the remote port
    ks -> GetRemoteServer() -> Close();

    
this -> refShadowServer -> Release();
    
this -> refGuiServer -> Release();
    
this -> refParticleServer -> Release();
    
this -> refVariableServer -> Release();
    
this -> refSceneServer -> Release();
    
this -> refConServer -> Release();
    
this -> refInputServer -> Release();
    
this -> refGfxServer -> Release();
    
this -> refResourceServer -> Release();
    
this -> refScriptServer -> Release();
    
this -> refAnimationServer -> Release();

    
// this->refVideoServer->Release();
    
// this->refLocaleServer->Release();
    
// this->refPrefServer->Release();
    
// this->refAudioServer->Release();

    
return   true ;
}

///  Main loop
void  nAppFrame::RunNebula()
{
    n_assert(
this -> isOpen);

    
bool  run  =   true ;

    
///  Trigger GfxServer (Windows Messages) && Ping Script Quit Request
     while  ( run  =  refGfxServer -> Trigger()  &&   this -> refScriptServer -> Trigger() )
    {
        
///  Trigger TimeServer
        nTimeServer::Instance() -> Trigger();
        
double  time  =  nTimeServer::Instance() -> GetTime();

        
///  Trigger InputServer
         this -> refInputServer -> Trigger(time);

        
///  Trigger Logic
         this -> OnFrame();

        
///  Begin Scene (Begin Frame)
         if  ( refSceneServer -> BeginScene(view) )
        {
            
//  Trigger Particle Server
            refParticleServer -> Trigger();

            
//  Render 3D
             this -> OnRender3D();

            
//  Render Scene
            refSceneServer -> RenderScene();

            
//  End Scene
            refSceneServer -> EndScene();

            
//  Render 2D
             this -> OnRender2D();

            
//  Present Scene (End Frame)
            refSceneServer -> PresentScene();
        }

        
///  Flush Events
         this -> refInputServer -> FlushEvents();
    }
}

///  OnRender3d
void  nAppFrame::OnRender3D()
{
    
for  ( size_t i  =   0 ; i  <  m_nodes.GetCount();  ++ i )
    {
        
this -> refSceneServer -> Attach(m_nodes.GetRenderContextAt(i));
    }

    
if  ( m_fpOnRender3D )
    {
        m_fpOnRender3D();
    }
}

///  OnRender2d
void  nAppFrame::OnRender2D()
{
    
if  ( m_fpOnRender2D )
    {
        m_fpOnRender2D();
    }
}

///  logic trigger
void  nAppFrame::OnFrame()
{
    
///  update camera
     this -> OnCameraControll();

    
///  update node list
     static  unsigned  int  nFrameID  =   0 ;
    
this -> m_nodes.Trigger(nTimeServer::Instance() -> GetTime(), nFrameID ++ );

    
if  ( m_fpOnFrame )
    {
        m_fpOnFrame();
    }
}

///  camera controll
void  nAppFrame::OnCameraControll()
{
    
//  Default Camera Controller
     if  (  ! this -> refGuiServer -> IsMouseOverGui() )
    {
        
//  Render Debug
         if  ( refInputServer -> GetButton( " debug " ) )
        {
            
if  ( refSceneServer -> GetRenderDebug() )
            {
                refSceneServer
-> SetRenderDebug( false );
            } 
            
else  
            {
                refSceneServer
-> SetRenderDebug( true );
            }
        }

        
//  give inputs to camControl
         this -> m_ccam.SetResetButton(refInputServer -> GetButton( " reset " ));
        
this -> m_ccam.SetLookButton(refInputServer -> GetButton( " look " ));
        
this -> m_ccam.SetPanButton(refInputServer -> GetButton( " pan " ));
        
this -> m_ccam.SetZoomButton(refInputServer -> GetButton( " zoom " ));
        
this -> m_ccam.SetSliderLeft(refInputServer -> GetSlider( " left " ));
        
this -> m_ccam.SetSliderRight(refInputServer -> GetSlider( " right " ));
        
this -> m_ccam.SetSliderUp(refInputServer -> GetSlider( " up " ));
        
this -> m_ccam.SetSliderDown(refInputServer -> GetSlider( " down " ));

        
//  update view and get the actual viewMatrix
         this -> m_ccam.Update();
        
this -> view. set ( this -> m_ccam.GetViewMatrix());
    }
}

以下是使用实例代码:

/* ************************************************************************** */
/*     Nebula2 - Tutorial 15                                                     */
/*   Simple Application  Framework                                             */
/*   author: happykevins                                                         */
/* ************************************************************************** */

#include 
" kernel/nkernelserver.h "
#include 
" gfx2/ngfxserver2.h "
#include 
" ../NebulaUtils/nappframe.h "
#include 
" ../NebulaUtils/nutildefs.h "

void  Render3D()
{
    
//  Write 3D Render Code Here.
}

void  Render2D()
{
    
//  draw cubes
    vector3 CenterPoint( 0 0.5f 0 );
    
float  fSize  =   0.5f ;
    vector3 v[
8 ];
    v[
0 ]. set (CenterPoint.x  -  fSize, CenterPoint.y  -  fSize, CenterPoint.z  -  fSize);
    v[
1 ]. set (CenterPoint.x  +  fSize, CenterPoint.y  -  fSize, CenterPoint.z  -  fSize);
    v[
2 ]. set (CenterPoint.x  +  fSize, CenterPoint.y  +  fSize, CenterPoint.z  -  fSize);
    v[
3 ]. set (CenterPoint.x  -  fSize, CenterPoint.y  +  fSize, CenterPoint.z  -  fSize);
    v[
4 ]. set (CenterPoint.x  -  fSize, CenterPoint.y  -  fSize, CenterPoint.z  +  fSize);
    v[
5 ]. set (CenterPoint.x  +  fSize, CenterPoint.y  -  fSize, CenterPoint.z  +  fSize);
    v[
6 ]. set (CenterPoint.x  +  fSize, CenterPoint.y  +  fSize, CenterPoint.z  +  fSize);
    v[
7 ]. set (CenterPoint.x  -  fSize, CenterPoint.y  +  fSize, CenterPoint.z  +  fSize);

    vector3 cube[
16 =  {
        v[
1 ], v[ 0 ], v[ 4 ], v[ 5 ],
        v[
1 ], v[ 2 ], v[ 6 ], v[ 5 ],
        v[
3 ], v[ 2 ], v[ 6 ], v[ 7 ],
        v[
3 ], v[ 0 ], v[ 4 ], v[ 7 ]
    };

    vector3 CenterPoint1(
0 1.5f 0 );
    
float  fSize1  =   0.5f ;
    vector3 v1[
8 ];
    v1[
0 ]. set (CenterPoint1.x  -  fSize1, CenterPoint1.y  -  fSize1, CenterPoint1.z  -  fSize1);
    v1[
1 ]. set (CenterPoint1.x  +  fSize1, CenterPoint1.y  -  fSize1, CenterPoint1.z  -  fSize1);
    v1[
2 ]. set (CenterPoint1.x  +  fSize1, CenterPoint1.y  +  fSize1, CenterPoint1.z  -  fSize1);
    v1[
3 ]. set (CenterPoint1.x  -  fSize1, CenterPoint1.y  +  fSize1, CenterPoint1.z  -  fSize1);
    v1[
4 ]. set (CenterPoint1.x  -  fSize1, CenterPoint1.y  -  fSize1, CenterPoint1.z  +  fSize1);
    v1[
5 ]. set (CenterPoint1.x  +  fSize1, CenterPoint1.y  -  fSize1, CenterPoint1.z  +  fSize1);
    v1[
6 ]. set (CenterPoint1.x  +  fSize1, CenterPoint1.y  +  fSize1, CenterPoint1.z  +  fSize1);
    v1[
7 ]. set (CenterPoint1.x  -  fSize1, CenterPoint1.y  +  fSize1, CenterPoint1.z  +  fSize1);

    vector3 cube1[
16 =  {
        v1[
1 ], v1[ 0 ], v1[ 4 ], v1[ 5 ],
        v1[
1 ], v1[ 2 ], v1[ 6 ], v1[ 5 ],
        v1[
3 ], v1[ 2 ], v1[ 6 ], v1[ 7 ],
        v1[
3 ], v1[ 0 ], v1[ 4 ], v1[ 7 ]
    };

    nGfxServer2::Instance()
-> BeginLines();

    nGfxServer2::Instance()
-> DrawLines3d(cube,    8 , vector4( 1.0f 0 0 0.5f ) );
    nGfxServer2::Instance()
-> DrawLines3d(cube + 8 8 , vector4( 1.0f 0 0 0.5f ) );

    nGfxServer2::Instance()
-> DrawLines3d(cube1,    8 , vector4( 0 1.0f 0 0.5f ) );
    nGfxServer2::Instance()
-> DrawLines3d(cube1 + 8 8 , vector4( 0 1.0f 0 0.5f ) );

    nGfxServer2::Instance()
-> EndLines();

    vector3 LineH[
22 ];
    vector3 LineV[
22 ];
    
float  fLen  =   5.0f ;
    
for ( int  i  =   0 ; i  <   11 ; i ++ )
    {
        LineH[ i 
*   2 ]. set ( 0   -  fLen,  0 , i - fLen);
        LineH[ i 
*   2   +   1 ]. set ( 10.0f   -  fLen,  0 , i  -  fLen);
    }

    
for (i  =   0 ; i  <   11 ; i ++ )
    {
        LineV[ i 
*   2 ]. set (i -  fLen,  0 0   -  fLen);
        LineV[ i 
*   2   +   1 ]. set (i -  fLen,  0 10.0f -  fLen);
    }

    
//  draw grids
    nGfxServer2::Instance() -> BeginLines();

    
for (i  =   0 ; i  <   11 ; i ++ )
    {
        nGfxServer2::Instance()
-> DrawLines3d(LineH  +  i  *   2 ,    2 , vector4( 1.0f 0 1.0f 0.5f ) );
    }

    
for (i  =   0 ; i  <   11 ; i ++ )
    {
        nGfxServer2::Instance()
-> DrawLines3d(LineV  +  i  *   2 ,    2 , vector4( 1.0f 0 1.0f 0.5f ) );
    }

    nGfxServer2::Instance()
-> EndLines();
}

/// ----------------------------------------------------------------------------
///  +Application
int  main( int  argc,  const   char **  argv)
{
    
//  生成一个nAppFrame的实例
    nAppFrame app;

    
//  注册渲染函数
    app.m_fpOnRender2D  =  Render2D;
    app.m_fpOnRender3D 
=  Render3D;

    
//  初始化引擎
     if  ( app.OpenNebula() )
    {
        
//  启动引擎主循环
        app.RunNebula();
    }

    
//  关闭引擎
    app.CloseNebula();

    
return   0 ;
}
///  -Application
/// ----------------------------------------------------------------------------
-The End-



http://www.niftyadmin.cn/n/3647769.html

相关文章

Bug经典回放(四)

Bug现象: 还是调试别人的程序. 这次是GUI. 我们的GUI是基于SDL OpenGL的. 程序运行以后进行视频播放.在出现的工具条上不停的点击几下后. 整个GUI系统均停止响应. 工具条有个属性.在开始播放音乐或者视频后.会根据播放引擎通过一个引擎来设置toolbar的属性. 比如.在同一…

一般拓扑学--From百度(看了这个,终于明白什么是拓扑了)

用点集的方法研究拓扑不变量的拓扑分支。它的前身是点集拓扑学。点集拓扑学产生于19世纪。G.康托尔建立了集合论&#xff0c;定义了欧几里得空间中的开集、闭集、导集等概念&#xff0c;获得了欧几里得空间拓扑结构的重要结果。1906年M.-R.弗雷歇把康托尔的集合论与函数空间的研…

和快手大牛的技术面谈,我先收藏为敬

前言 前段时间发放了学习资料给予自学java的同学们&#xff0c;自学虽好&#xff0c;但是架不住没有老师讲解重侧点&#xff08;实际上许多培训班的老师也是水分多多&#xff0c;甚至无实战经验&#xff09;&#xff0c;今天我就抽空把java零基础入门&#xff08;六个月&#…

恶搞的NVIDIA驱动

昨天做水波&#xff0c;遇到一个十分可恶的bug。程序在笔记本的84.xx驱动下十分正常。在台式机的6600显卡&#xff0c;84.xx驱动下工作基本正常&#xff0c;但是水波还是能看到的&#xff0c;但是如果shader所在路径不是很深的话&#xff0c;同一个VS链接到不同的PS会报错&…

和快手大牛的技术面谈,瞬间高大上了!

前言 Mysql的锁机制确实非常重要&#xff0c;所以在这里做一个全面的总结整理&#xff0c;便于以后的查阅&#xff0c;也分享给大家。 Mysql的锁机制还是有点难理解的&#xff0c;所以这篇文章采用图文结合的方式讲解难点&#xff0c;帮助大家理解&#xff0c;讲解的主要内容…

VTF的水波终于移植完了.

以前那个破2D水终于移植到GPU上了.这个是质点弹簧系统,下来可以模拟波动方程了. 128 x 128的mesh grid, CPU计算的时候fps只有12fps.现在已经有80fps了.回头再用vtune查查什么地方慢. 估计上到120fps问题应该不大的.用了NV的VTF. 发现恶心的是VTF只支持32bit float纹理. 两种格…

和网易大佬的技术面谈,冲刺7天拿下Offer!

前言 MySQL 是最流行的关系型数据库管理系统(RDBMS)之一。 MySQL作为一个关系型数据库管理系统&#xff0c;因为其速度、可靠性和适应性而备受关注。大多数人都认为在不需要事务化处理的情况下&#xff0c;MySQL是管理内容最好的选择。虽然功能未必很强大&#xff0c;但因为它…

Nebula2探秘11-Simple Window

Nebula2探秘11-Simple Windowhappykevins文前面的10节主要讲的是Nebula2内核层模块的应用&#xff0c;所以一直在黑黑Dos控制台下工作&#xff0c;可能大家已经非常想念Windows窗口了:) 从本章起&#xff0c;我将开始介绍Nebula2的应用层模块&#xff0c;并以一个最简单的Windo…