forked from mirror/openmw-tes3mp
- removed caelum (we can get it from the git history, if needed)
- added code for moon rendering (they are not visible by default)
This commit is contained in:
parent
090c0586a0
commit
6aac3d4b77
1 changed files with 165 additions and 121 deletions
|
@ -26,11 +26,39 @@ namespace MWRender
|
||||||
const Vector3& pInitialPosition,
|
const Vector3& pInitialPosition,
|
||||||
SceneNode* pRootNode
|
SceneNode* pRootNode
|
||||||
);
|
);
|
||||||
|
CelestialBody();
|
||||||
|
|
||||||
void setPosition(const Vector3& pPosition);
|
void setPosition(const Vector3& pPosition);
|
||||||
|
void setVisible(const bool visible) { mNode->setVisible(visible); };
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
|
virtual void init(const String& pTextureName,
|
||||||
|
const unsigned int pInitialSize,
|
||||||
|
const Vector3& pInitialPosition,
|
||||||
|
SceneNode* pRootNode);
|
||||||
|
|
||||||
SceneNode* mNode;
|
SceneNode* mNode;
|
||||||
|
MaterialPtr mMaterial;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The moons need a seperate class because of their shader (which allows them to be partially transparent)
|
||||||
|
*/
|
||||||
|
class Moon : public CelestialBody
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Moon( const String& pTextureName,
|
||||||
|
const unsigned int pInitialSize,
|
||||||
|
const Vector3& pInitialPosition,
|
||||||
|
SceneNode* pRootNode
|
||||||
|
);
|
||||||
|
|
||||||
|
void setVisibility(const float pVisibility);
|
||||||
|
///< set the transparency factor for this moon
|
||||||
|
|
||||||
|
void setColour(const ColourValue& pColour);
|
||||||
|
|
||||||
|
/// \todo Moon phases
|
||||||
};
|
};
|
||||||
|
|
||||||
CelestialBody::CelestialBody( const String& textureName,
|
CelestialBody::CelestialBody( const String& textureName,
|
||||||
|
@ -38,34 +66,11 @@ namespace MWRender
|
||||||
const Vector3& pInitialPosition,
|
const Vector3& pInitialPosition,
|
||||||
SceneNode* pRootNode)
|
SceneNode* pRootNode)
|
||||||
{
|
{
|
||||||
SceneManager* sceneMgr = pRootNode->getCreator();
|
init(textureName, initialSize, pInitialPosition, pRootNode);
|
||||||
|
}
|
||||||
const float scale = initialSize*700.f;
|
|
||||||
|
CelestialBody::CelestialBody()
|
||||||
Vector3 finalPosition = pInitialPosition.normalisedCopy() * CELESTIAL_BODY_DISTANCE;
|
{
|
||||||
|
|
||||||
static unsigned int bodyCount=0;
|
|
||||||
|
|
||||||
// Create a camera-aligned billboard
|
|
||||||
BillboardSet* bbSet = sceneMgr->createBillboardSet("SkyBillboardSet"+StringConverter::toString(bodyCount), 1);
|
|
||||||
bbSet->setDefaultDimensions(scale, scale);
|
|
||||||
bbSet->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY);
|
|
||||||
SceneNode* mNode = pRootNode->createChildSceneNode();
|
|
||||||
mNode->setPosition(finalPosition);
|
|
||||||
mNode->attachObject(bbSet);
|
|
||||||
bbSet->createBillboard(0,0,0);
|
|
||||||
|
|
||||||
MaterialPtr material = MaterialManager::getSingleton().create("CelestialBody"+StringConverter::toString(bodyCount), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
|
||||||
material->removeAllTechniques();
|
|
||||||
Pass* p = material->createTechnique()->createPass();
|
|
||||||
p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
|
||||||
p->setDepthCheckEnabled(false);
|
|
||||||
p->setDepthWriteEnabled(false);
|
|
||||||
p->createTextureUnitState(textureName /*"textures\\tx_sun_05.dds"*/);
|
|
||||||
bbSet->setMaterialName("CelestialBody"+StringConverter::toString(bodyCount));
|
|
||||||
|
|
||||||
bodyCount++;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CelestialBody::setPosition(const Vector3& pPosition)
|
void CelestialBody::setPosition(const Vector3& pPosition)
|
||||||
|
@ -75,6 +80,115 @@ namespace MWRender
|
||||||
mNode->setPosition(finalPosition);
|
mNode->setPosition(finalPosition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CelestialBody::init(const String& textureName,
|
||||||
|
const unsigned int initialSize,
|
||||||
|
const Vector3& pInitialPosition,
|
||||||
|
SceneNode* pRootNode)
|
||||||
|
{
|
||||||
|
SceneManager* sceneMgr = pRootNode->getCreator();
|
||||||
|
|
||||||
|
const float scale = initialSize*550.f;
|
||||||
|
|
||||||
|
Vector3 finalPosition = pInitialPosition.normalisedCopy() * CELESTIAL_BODY_DISTANCE;
|
||||||
|
|
||||||
|
static unsigned int bodyCount=0;
|
||||||
|
|
||||||
|
/// \todo These billboards are not 100% correct, might want to revisit them later
|
||||||
|
BillboardSet* bbSet = sceneMgr->createBillboardSet("SkyBillboardSet"+StringConverter::toString(bodyCount), 1);
|
||||||
|
bbSet->setDefaultDimensions(scale, scale);
|
||||||
|
bbSet->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY+1);
|
||||||
|
bbSet->setBillboardType(BBT_PERPENDICULAR_COMMON);
|
||||||
|
bbSet->setCommonDirection( -pInitialPosition.normalisedCopy() );
|
||||||
|
mNode = pRootNode->createChildSceneNode();
|
||||||
|
mNode->setPosition(finalPosition);
|
||||||
|
mNode->attachObject(bbSet);
|
||||||
|
bbSet->createBillboard(0,0,0);
|
||||||
|
|
||||||
|
mMaterial = MaterialManager::getSingleton().create("CelestialBody"+StringConverter::toString(bodyCount), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
||||||
|
mMaterial->removeAllTechniques();
|
||||||
|
Pass* p = mMaterial->createTechnique()->createPass();
|
||||||
|
p->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||||
|
p->setDepthCheckEnabled(false);
|
||||||
|
p->setDepthWriteEnabled(false);
|
||||||
|
p->setSelfIllumination(1.0,1.0,1.0);
|
||||||
|
p->setDiffuse(0.0,0.0,0.0,1.0);
|
||||||
|
p->setAmbient(0.0,0.0,0.0);
|
||||||
|
p->createTextureUnitState(textureName);
|
||||||
|
bbSet->setMaterialName("CelestialBody"+StringConverter::toString(bodyCount));
|
||||||
|
|
||||||
|
bodyCount++;
|
||||||
|
}
|
||||||
|
|
||||||
|
Moon::Moon( const String& textureName,
|
||||||
|
const unsigned int initialSize,
|
||||||
|
const Vector3& pInitialPosition,
|
||||||
|
SceneNode* pRootNode)
|
||||||
|
{
|
||||||
|
init(textureName, initialSize, pInitialPosition, pRootNode);
|
||||||
|
|
||||||
|
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
||||||
|
HighLevelGpuProgramPtr vshader;
|
||||||
|
if (mgr.resourceExists("Moon_VP"))
|
||||||
|
vshader = mgr.getByName("Moon_VP");
|
||||||
|
else
|
||||||
|
vshader = mgr.createProgram("Moon_VP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_VERTEX_PROGRAM);
|
||||||
|
vshader->setParameter("profiles", "vs_2_x arbvp1");
|
||||||
|
vshader->setParameter("entry_point", "main_vp");
|
||||||
|
StringUtil::StrStreamType outStream;
|
||||||
|
outStream <<
|
||||||
|
"void main_vp( \n"
|
||||||
|
" float4 position : POSITION, \n"
|
||||||
|
" in float2 uv : TEXCOORD0, \n"
|
||||||
|
" out float2 oUV : TEXCOORD0, \n"
|
||||||
|
" out float4 oPosition : POSITION, \n"
|
||||||
|
" uniform float4x4 worldViewProj \n"
|
||||||
|
") \n"
|
||||||
|
"{ \n"
|
||||||
|
" oUV = uv; \n"
|
||||||
|
" oPosition = mul( worldViewProj, position ); \n"
|
||||||
|
"}";
|
||||||
|
vshader->setSource(outStream.str());
|
||||||
|
vshader->load();
|
||||||
|
vshader->getDefaultParameters()->setNamedAutoConstant("worldViewProj", GpuProgramParameters::ACT_WORLDVIEWPROJ_MATRIX);
|
||||||
|
mMaterial->getTechnique(0)->getPass(0)->setVertexProgram(vshader->getName());
|
||||||
|
|
||||||
|
HighLevelGpuProgramPtr fshader;
|
||||||
|
if (mgr.resourceExists("Moon_FP"))
|
||||||
|
fshader = mgr.getByName("Moon_FP");
|
||||||
|
else
|
||||||
|
fshader = mgr.createProgram("Moon_FP", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, "cg", GPT_FRAGMENT_PROGRAM);
|
||||||
|
|
||||||
|
fshader->setParameter("profiles", "ps_2_x arbfp1");
|
||||||
|
fshader->setParameter("entry_point", "main_fp");
|
||||||
|
StringUtil::StrStreamType outStream2;
|
||||||
|
outStream2 <<
|
||||||
|
"void main_fp( \n"
|
||||||
|
" in float2 uv : TEXCOORD0, \n"
|
||||||
|
" out float4 oColor : COLOR, \n"
|
||||||
|
" uniform sampler2D texture : TEXUNIT0, \n"
|
||||||
|
" uniform float visibilityFactor, \n"
|
||||||
|
" uniform float4 emissive \n"
|
||||||
|
") \n"
|
||||||
|
"{ \n"
|
||||||
|
" float4 tex = tex2D(texture, uv); \n"
|
||||||
|
" oColor = float4(emissive.xyz,1) * tex2D(texture, uv) * float4(1,1,1,visibilityFactor); \n"
|
||||||
|
"}";
|
||||||
|
fshader->setSource(outStream2.str());
|
||||||
|
fshader->load();
|
||||||
|
fshader->getDefaultParameters()->setNamedAutoConstant("emissive", GpuProgramParameters::ACT_SURFACE_EMISSIVE_COLOUR);
|
||||||
|
mMaterial->getTechnique(0)->getPass(0)->setFragmentProgram(fshader->getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Moon::setVisibility(const float pVisibility)
|
||||||
|
{
|
||||||
|
mMaterial->getTechnique(0)->getPass(0)->getFragmentProgramParameters()->setNamedConstant("visibilityFactor", Real(pVisibility));
|
||||||
|
}
|
||||||
|
|
||||||
|
void Moon::setColour(const ColourValue& pColour)
|
||||||
|
{
|
||||||
|
mMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(pColour);
|
||||||
|
}
|
||||||
|
|
||||||
class MWSkyManager : public SkyManager
|
class MWSkyManager : public SkyManager
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -101,11 +215,13 @@ namespace MWRender
|
||||||
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half,
|
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half,
|
||||||
/// 3 waxing or waning gibbous, 4 full moon
|
/// 3 waxing or waning gibbous, 4 full moon
|
||||||
|
|
||||||
virtual void setMoonColour (bool red) {}
|
virtual void setMoonColour (bool red);
|
||||||
///< change Secunda colour to red
|
///< change Secunda colour to red
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CelestialBody* mSun;
|
CelestialBody* mSun;
|
||||||
|
Moon* mMasser;
|
||||||
|
Moon* mSecunda;
|
||||||
|
|
||||||
Camera* mCamera;
|
Camera* mCamera;
|
||||||
Viewport* mViewport;
|
Viewport* mViewport;
|
||||||
|
@ -185,6 +301,12 @@ namespace MWRender
|
||||||
mViewport->setBackgroundColour(ColourValue(0.87, 0.87, 0.87));
|
mViewport->setBackgroundColour(ColourValue(0.87, 0.87, 0.87));
|
||||||
|
|
||||||
mSun = new CelestialBody("textures\\tx_sun_05.dds", 1, Vector3(0.4, 0.4, 1.0), mRootNode);
|
mSun = new CelestialBody("textures\\tx_sun_05.dds", 1, Vector3(0.4, 0.4, 1.0), mRootNode);
|
||||||
|
mMasser = new Moon("textures\\tx_masser_full.dds", 1, Vector3(-0.4, -0.4, 0.5), mRootNode);
|
||||||
|
mSecunda = new Moon("textures\\tx_secunda_full.dds", 1, Vector3(0.4, -0.4, 0.5), mRootNode);
|
||||||
|
mMasser->setVisibility(0.2);
|
||||||
|
mSecunda->setVisibility(0.2);
|
||||||
|
mMasser->setVisible(false);
|
||||||
|
mSecunda->setVisible(false);
|
||||||
|
|
||||||
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
HighLevelGpuProgramManager& mgr = HighLevelGpuProgramManager::getSingleton();
|
||||||
|
|
||||||
|
@ -230,7 +352,7 @@ namespace MWRender
|
||||||
// Clouds
|
// Clouds
|
||||||
NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif");
|
NifOgre::NIFLoader::load("meshes\\sky_clouds_01.nif");
|
||||||
Entity* clouds_ent = mSceneMgr->createEntity("meshes\\sky_clouds_01.nif");
|
Entity* clouds_ent = mSceneMgr->createEntity("meshes\\sky_clouds_01.nif");
|
||||||
clouds_ent->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY+1);
|
clouds_ent->setRenderQueueGroup(RENDER_QUEUE_SKIES_EARLY+2);
|
||||||
SceneNode* clouds_node = mRootNode->createChildSceneNode();
|
SceneNode* clouds_node = mRootNode->createChildSceneNode();
|
||||||
clouds_node->attachObject(clouds_ent);
|
clouds_node->attachObject(clouds_ent);
|
||||||
mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial();
|
mCloudMaterial = clouds_ent->getSubEntity(0)->getMaterial();
|
||||||
|
@ -279,7 +401,6 @@ namespace MWRender
|
||||||
"{ \n"
|
"{ \n"
|
||||||
" uv += float2(1,1) * time * 0.01; \n" // Scroll in x,y direction
|
" uv += float2(1,1) * time * 0.01; \n" // Scroll in x,y direction
|
||||||
" float4 tex = tex2D(texture, uv); \n"
|
" float4 tex = tex2D(texture, uv); \n"
|
||||||
" clip(tex.a<0.5); \n"
|
|
||||||
" oColor = color * float4(emissive.xyz,1) * tex2D(texture, uv); \n"
|
" oColor = color * float4(emissive.xyz,1) * tex2D(texture, uv); \n"
|
||||||
"}";
|
"}";
|
||||||
mCloudFragmentShader->setSource(outStream2.str());
|
mCloudFragmentShader->setSource(outStream2.str());
|
||||||
|
@ -305,7 +426,7 @@ namespace MWRender
|
||||||
mCloudMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0);
|
mCloudMaterial->getTechnique(0)->getPass(0)->setSelfIllumination(1.0, 1.0, 1.0);
|
||||||
// Disable depth writing so that the sky does not cover any objects
|
// Disable depth writing so that the sky does not cover any objects
|
||||||
mCloudMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
|
mCloudMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
|
||||||
//mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
|
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setDepthWriteEnabled(false);
|
||||||
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
mAtmosphereMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||||
mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
mCloudMaterial->getTechnique(0)->getPass(0)->setSceneBlending(SBT_TRANSPARENT_ALPHA);
|
||||||
|
|
||||||
|
@ -315,6 +436,8 @@ namespace MWRender
|
||||||
MWSkyManager::~MWSkyManager()
|
MWSkyManager::~MWSkyManager()
|
||||||
{
|
{
|
||||||
delete mSun;
|
delete mSun;
|
||||||
|
delete mMasser;
|
||||||
|
delete mSecunda;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MWSkyManager::update(float duration)
|
void MWSkyManager::update(float duration)
|
||||||
|
@ -337,89 +460,10 @@ namespace MWRender
|
||||||
mRootNode->setVisible(false);
|
mRootNode->setVisible(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void MWSkyManager::setMoonColour (bool red)
|
||||||
//
|
|
||||||
// Implements a Caelum sky with default settings.
|
|
||||||
//
|
|
||||||
// Note: this is intended as a temporary solution to provide some form of
|
|
||||||
// sky rendering. This code will obviously need significant tailoring to
|
|
||||||
// support fidelity with Morrowind's rendering. Before doing major work
|
|
||||||
// on this class, more research should be done to determine whether
|
|
||||||
// Caelum or another plug-in such as SkyX would be best for the long-term.
|
|
||||||
//
|
|
||||||
class CaelumManager : public SkyManager
|
|
||||||
{
|
{
|
||||||
protected:
|
mSecunda->setColour( red ? ColourValue(1.0, 0.0, 0.0)
|
||||||
Caelum::CaelumSystem* mpCaelumSystem;
|
: ColourValue(1.0, 1.0, 1.0));
|
||||||
|
|
||||||
public:
|
|
||||||
CaelumManager (Ogre::RenderWindow* pRenderWindow,
|
|
||||||
Ogre::Camera* pCamera,
|
|
||||||
const boost::filesystem::path& resDir);
|
|
||||||
virtual ~CaelumManager ();
|
|
||||||
|
|
||||||
virtual void update(float duration) {}
|
|
||||||
|
|
||||||
virtual void enable() {}
|
|
||||||
|
|
||||||
virtual void disable() {}
|
|
||||||
|
|
||||||
virtual void setHour (double hour) {}
|
|
||||||
///< will be called even when sky is disabled.
|
|
||||||
|
|
||||||
virtual void setDate (int day, int month) {}
|
|
||||||
///< will be called even when sky is disabled.
|
|
||||||
|
|
||||||
virtual int getMasserPhase() const { return 0; }
|
|
||||||
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half,
|
|
||||||
/// 3 waxing or waning gibbous, 4 full moon
|
|
||||||
|
|
||||||
virtual int getSecundaPhase() const { return 0; }
|
|
||||||
///< 0 new moon, 1 waxing or waning cresecent, 2 waxing or waning half,
|
|
||||||
/// 3 waxing or waning gibbous, 4 full moon
|
|
||||||
|
|
||||||
virtual void setMoonColour (bool red) {}
|
|
||||||
};
|
|
||||||
|
|
||||||
CaelumManager::CaelumManager (Ogre::RenderWindow* pRenderWindow,
|
|
||||||
Ogre::Camera* pCamera,
|
|
||||||
const boost::filesystem::path& resDir)
|
|
||||||
: mpCaelumSystem (NULL)
|
|
||||||
{
|
|
||||||
using namespace Caelum;
|
|
||||||
|
|
||||||
assert(pCamera);
|
|
||||||
assert(pRenderWindow);
|
|
||||||
|
|
||||||
// Load the Caelum resources
|
|
||||||
//
|
|
||||||
ResourceGroupManager::getSingleton().addResourceLocation((resDir / "caelum").string(), "FileSystem", "Caelum");
|
|
||||||
ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
|
|
||||||
|
|
||||||
// Load the Caelum resources
|
|
||||||
//
|
|
||||||
Ogre::SceneManager* pScene = pCamera->getSceneManager();
|
|
||||||
Caelum::CaelumSystem::CaelumComponent componentMask = CaelumSystem::CAELUM_COMPONENTS_DEFAULT;
|
|
||||||
mpCaelumSystem = new Caelum::CaelumSystem (Root::getSingletonPtr(), pScene, componentMask);
|
|
||||||
|
|
||||||
// Set time acceleration.
|
|
||||||
mpCaelumSystem->getUniversalClock()->setTimeScale(128);
|
|
||||||
|
|
||||||
// Disable fog since OpenMW is handling OGRE fog elsewhere
|
|
||||||
mpCaelumSystem->setManageSceneFog(false);
|
|
||||||
|
|
||||||
// Change the camera far distance to make sure the sky is not clipped
|
|
||||||
pCamera->setFarClipDistance(50000);
|
|
||||||
|
|
||||||
// Register Caelum as an OGRE listener
|
|
||||||
pRenderWindow->addListener(mpCaelumSystem);
|
|
||||||
Root::getSingletonPtr()->addFrameListener(mpCaelumSystem);
|
|
||||||
}
|
|
||||||
|
|
||||||
CaelumManager::~CaelumManager()
|
|
||||||
{
|
|
||||||
if (mpCaelumSystem)
|
|
||||||
mpCaelumSystem->shutdown (false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates and connects the sky rendering component to OGRE.
|
/// Creates and connects the sky rendering component to OGRE.
|
||||||
|
@ -433,12 +477,12 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
SkyManager* pSkyManager = NULL;
|
SkyManager* pSkyManager = NULL;
|
||||||
|
|
||||||
//try
|
try
|
||||||
//{
|
{
|
||||||
//pSkyManager = new CaelumManager(pRenderWindow, pCamera, resDir);
|
//pSkyManager = new CaelumManager(pRenderWindow, pCamera, resDir);
|
||||||
pSkyManager = new MWSkyManager(pMwRoot, pCamera);
|
pSkyManager = new MWSkyManager(pMwRoot, pCamera);
|
||||||
//}
|
}
|
||||||
/*catch (Ogre::Exception& e)
|
catch (Ogre::Exception& e)
|
||||||
{
|
{
|
||||||
std::cout << "\nOGRE Exception when attempting to add sky: "
|
std::cout << "\nOGRE Exception when attempting to add sky: "
|
||||||
<< e.getFullDescription().c_str() << std::endl;
|
<< e.getFullDescription().c_str() << std::endl;
|
||||||
|
@ -447,7 +491,7 @@ namespace MWRender
|
||||||
{
|
{
|
||||||
std::cout << "\nException when attempting to add sky: "
|
std::cout << "\nException when attempting to add sky: "
|
||||||
<< e.what() << std::endl;
|
<< e.what() << std::endl;
|
||||||
}*/
|
}
|
||||||
|
|
||||||
return pSkyManager;
|
return pSkyManager;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue