Merge remote-tracking branch 'ryzomcore/develop' into feature/develop-atys

feature/develop-atys
kaetemi 4 years ago
commit 5c3b0cf14b

@ -102,6 +102,7 @@ SET(RYZOM_CLIENT_CREATE_ACCOUNT_URL "https://open.ryzom.dev/ams/" CACHE STRING
SET(RYZOM_CLIENT_EDIT_ACCOUNT_URL "https://open.ryzom.dev/ams/" CACHE STRING "Ryzom Client Edit Account URL")
SET(RYZOM_CLIENT_FORGET_PASSWORD_URL "https://open.ryzom.dev/ams/" CACHE STRING "Ryzom Client Forget Password URL")
SET(RYZOM_CLIENT_PATCH_URL "https://cdn.ryzom.dev/open/patch/" CACHE STRING "Ryzom Client Patch URL")
SET(RYZOM_CLIENT_APP_NAME "default")
SET(RYZOM_WEBIG_MAIN_URL "https://open.ryzom.dev/" CACHE STRING "Ryzom Client WebIG Main URL")
SET(RYZOM_WEBIG_TRUSTED_DOMAIN "open.ryzom.dev" CACHE STRING "Ryzom Client WebIG Trusted Domain")
@ -114,6 +115,7 @@ IF(WITH_RYZOM_LIVE)
SET(RYZOM_CLIENT_EDIT_ACCOUNT_URL "https://account.ryzom.com/payment_profile/index.php")
SET(RYZOM_CLIENT_FORGET_PASSWORD_URL "https://account.ryzom.com/payment_profile/lost_secure_password.php")
SET(RYZOM_CLIENT_PATCH_URL "http://dl.ryzom.com/patch_live")
SET(RYZOM_CLIENT_APP_NAME "ryzom_live")
SET(RYZOM_WEBIG_MAIN_URL "https://app.ryzom.com/")
SET(RYZOM_WEBIG_TRUSTED_DOMAIN "app.ryzom.com")

@ -37,6 +37,7 @@
#cmakedefine RYZOM_CLIENT_EDIT_ACCOUNT_URL "${RYZOM_CLIENT_EDIT_ACCOUNT_URL}"
#cmakedefine RYZOM_CLIENT_FORGET_PASSWORD_URL "${RYZOM_CLIENT_FORGET_PASSWORD_URL}"
#cmakedefine RYZOM_CLIENT_PATCH_URL "${RYZOM_CLIENT_PATCH_URL}"
#cmakedefine RYZOM_CLIENT_APP_NAME "${RYZOM_CLIENT_APP_NAME}"
#cmakedefine RYZOM_WEBIG_MAIN_URL "${RYZOM_WEBIG_MAIN_URL}"
#cmakedefine RYZOM_WEBIG_TRUSTED_DOMAIN "${RYZOM_WEBIG_TRUSTED_DOMAIN}"

@ -28,6 +28,7 @@
#include "nel/gui/ctrl_button.h"
#include "nel/gui/group_table.h"
#include "nel/gui/html_element.h"
#include "nel/gui/html_parser.h"
#include "nel/gui/css_style.h"
// forward declaration
@ -376,7 +377,9 @@ namespace NLGUI
// true if renderer is waiting for css files to finish downloading (link rel=stylesheet)
bool _WaitingForStylesheet;
// list of css file urls that are queued up for download
std::vector<std::string> _StylesheetQueue;
std::vector<CHtmlParser::StyleLink> _StylesheetQueue;
// <style> and downloaded <link rel=stylesheet> elements
std::vector<std::string> _HtmlStyles;
// Valid base href was found
bool _IgnoreBaseUrlTag;
@ -890,7 +893,7 @@ namespace NLGUI
std::string localBnpName(const std::string &url);
// add css file from <link href=".." rel="stylesheet"> to download queue
void addStylesheetDownload(std::vector<std::string> links);
void addStylesheetDownload(std::vector<CHtmlParser::StyleLink> links);
// stop all curl downalods (html and data)
void releaseDownloads();

@ -31,14 +31,23 @@ namespace NLGUI
class CHtmlParser
{
public:
// <link rel=stylesheet>
struct StyleLink
{
uint Index;
std::string Url;
StyleLink(uint i, const std::string &url) : Index(i), Url(url)
{ }
};
bool parseHtml(std::string htmlString) const;
// parse html string into DOM, extract <style> tags into styleString, <link stylesheet> urls into links
void getDOM(std::string htmlString, CHtmlElement &parent, std::string &styleString, std::vector<std::string> &links) const;
// parse html string into DOM, extract <style> and <link stylesheet> urls
void getDOM(std::string htmlString, CHtmlElement &parent, std::vector<std::string> &styles, std::vector<StyleLink> &links) const;
private:
// iterate over libxml html tree, build DOM, and join all <style> tags together
void parseNode(xmlNode *a_node, CHtmlElement &parent, std::string &styleString, std::vector<std::string> &links) const;
// iterate over libxml html tree, build DOM
void parseNode(xmlNode *a_node, CHtmlElement &parent, std::vector<std::string> &styles, std::vector<StyleLink> &links) const;
// read <style> tag and add its content to styleString
void parseStyle(xmlNode *a_node, std::string &styleString) const;

@ -731,11 +731,18 @@ struct CFile
static bool createDirectoryTree(const std::string &dirname);
/** Try to set the file access to read/write if not already set.
* On linux/macOS also set +x on directory.
* return true if the file doesn't exist or if the file already have RW access.
* \return true if RW access is granted
*/
static bool setRWAccess(const std::string &filename);
/** Try to set +x bit on linux/macOS to make file executable. no-op on Windows
* On Windows, always returns true, even if file does not exist.
* \return true if file exists and +x was set, false if operation failed.
*/
static bool setExecutable(const std::string &filename);
/** Delete a file if possible (change the write access if possible)
* \return true if the delete occurs.
*/

@ -921,7 +921,7 @@ void CRenderTrav::changeVPLightSetupMaterial(const CMaterial &mat, bool exclude
Driver->setUniform4f(IDriver::VertexProgram, program->idxLighted().Diffuse[i], color);
}
nlassert(_VPNumLights < MaxVPLight);
nlassert(_VPNumLights <= MaxVPLight);
if (i != _VPNumLights)
{
color= _VPLightDiffuse[i] * matDiff;
@ -1240,7 +1240,7 @@ std::string CRenderTrav::getLightVPFragmentNeLVP(uint numActivePointLights, uin
// Code frag written for 4 light max.
nlassert(MaxVPLight==4);
nlassert(numActivePointLights<=MaxVPLight-1);
nlassert(numActivePointLights<=MaxVPLight);
// Add LightingVPFragmentNormalize fragment?
if(normalize)

@ -858,21 +858,16 @@ namespace NLGUI
CFile::createDirectory( pathName );
}
void CGroupHTML::addStylesheetDownload(std::vector<std::string> links)
void CGroupHTML::addStylesheetDownload(const std::vector<CHtmlParser::StyleLink> links)
{
for(uint i = 0; i < links.size(); ++i)
{
std::string url = getAbsoluteUrl(links[i]);
std::string local = localImageName(url);
_StylesheetQueue.push_back(links[i]);
std::string url = getAbsoluteUrl(links[i].Url);
_StylesheetQueue.back().Url = url;
// insert only if url not already downloading
std::vector<std::string>::const_iterator it = std::find(_StylesheetQueue.begin(), _StylesheetQueue.end(), url);
if (it == _StylesheetQueue.end())
{
_StylesheetQueue.push_back(url);
// push to the front of the queue
Curls.push_front(CDataDownload(url, local, StylesheetType, NULL, "", ""));
}
// push to the front of the queue
Curls.push_front(CDataDownload(url, localImageName(url), StylesheetType, NULL, "", ""));
}
pumpCurlQueue();
}
@ -4184,19 +4179,28 @@ namespace NLGUI
// ***************************************************************************
void CGroupHTML::cssDownloadFinished(const std::string &url, const std::string &local)
{
// remove file from download queue
std::vector<std::string>::iterator it = std::find(_StylesheetQueue.begin(), _StylesheetQueue.end(), url);
if (it != _StylesheetQueue.end())
for(std::vector<CHtmlParser::StyleLink>::iterator it = _StylesheetQueue.begin();
it != _StylesheetQueue.end(); ++it)
{
_StylesheetQueue.erase(it);
}
if (it->Url == url)
{
// read downloaded file into HtmlStyles
if (CFile::fileExists(local) && it->Index < _HtmlStyles.size())
{
CIFile in;
if (in.open(local))
{
if (!in.readAll(_HtmlStyles[it->Index]))
{
nlwarning("Failed to read downloaded css file(%s), url(%s)", local.c_str(), url.c_str());
}
}
}
if (!CFile::fileExists(local))
{
return;
_StylesheetQueue.erase(it);
break;
}
}
parseStylesheetFile(local);
}
void CGroupHTML::renderDocument()
@ -4214,6 +4218,16 @@ namespace NLGUI
beginBuild();
removeContent();
// process all <style> and <link rel=stylesheet> elements
for(uint i = 0; i < _HtmlStyles.size(); ++i)
{
if (!_HtmlStyles[i].empty())
{
_Style.parseStylesheet(_HtmlStyles[i]);
}
}
_HtmlStyles.clear();
std::list<CHtmlElement>::iterator it = _HtmlDOM.Children.begin();
while(it != _HtmlDOM.Children.end())
{
@ -4821,9 +4835,6 @@ namespace NLGUI
// ***************************************************************************
bool CGroupHTML::parseHtml(const std::string &htmlString)
{
std::vector<std::string> links;
std::string styleString;
CHtmlElement *parsedDOM;
if (_CurrentHTMLElement == NULL)
{
@ -4836,16 +4847,28 @@ namespace NLGUI
parsedDOM = _CurrentHTMLElement;
}
std::vector<CHtmlParser::StyleLink> links;
CHtmlParser parser;
parser.getDOM(htmlString, *parsedDOM, styleString, links);
parser.getDOM(htmlString, *parsedDOM, _HtmlStyles, links);
if (!styleString.empty())
// <link> elements inserted from lua::parseHtml are ignored
if (_CurrentHTMLElement == NULL && !links.empty())
{
_Style.parseStylesheet(styleString);
addStylesheetDownload(links);
}
if (!links.empty())
else if (_CurrentHTMLElement != NULL)
{
addStylesheetDownload(links);
// Called from active element (lua)
// <style> order is not preserved as document is already being rendered
for(uint i = 0; i < _HtmlStyles.size(); ++i)
{
if (!_HtmlStyles[i].empty())
{
_Style.parseStylesheet(_HtmlStyles[i]);
}
}
_HtmlStyles.clear();
}
// this should rarely fail as first element should be <html>
@ -4856,7 +4879,7 @@ namespace NLGUI
{
if (it->Type == CHtmlElement::ELEMENT_NODE && it->Value == "html")
{
// more newly parsed childs from <body> into siblings
// move newly parsed childs from <body> into siblings
if (_CurrentHTMLElement) {
std::list<CHtmlElement>::iterator it2 = it->Children.begin();
while(it2 != it->Children.end())
@ -5417,7 +5440,7 @@ namespace NLGUI
// ***************************************************************************
void CGroupHTML::insertFormImageButton(const std::string &name, const std::string &tooltip, const std::string &src, const std::string &over, const std::string &formId, const std::string &action, uint32 minWidth, const std::string &templateName)
{
_FormSubmit.push_back(SFormSubmitButton(formId, name, "", "image"));
_FormSubmit.push_back(SFormSubmitButton(formId, name, "", "image", action));
// Action handler parameters
std::string param = "name=" + getId() + "|button=" + toString(_FormSubmit.size()-1);
@ -5428,7 +5451,7 @@ namespace NLGUI
// ***************************************************************************
void CGroupHTML::insertFormTextButton(const std::string &name, const std::string &tooltip, const std::string &value, const std::string &formId, const std::string &formAction, uint32 minWidth, const std::string &templateName)
{
_FormSubmit.push_back(SFormSubmitButton(formId, name, value, "submit"));
_FormSubmit.push_back(SFormSubmitButton(formId, name, value, "submit", formAction));
// Action handler parameters
string param = "name=" + getId() + "|button=" + toString(_FormSubmit.size()-1);
@ -6065,16 +6088,27 @@ namespace NLGUI
string name = elm.getAttribute("name");
string src = elm.getAttribute("src");
string over = elm.getAttribute("data-over-src");
string formId = elm.getAttribute("form");
string formAction = elm.getAttribute("formaction");
insertFormImageButton(name, tooltip, src, over, _Forms.back().id, "", minWidth, templateName);
if (formId.empty() && _FormOpen) {
formId = _Forms.back().id;
}
insertFormImageButton(name, tooltip, src, over, formId, formAction, minWidth, templateName);
}
else if (type == "button" || type == "submit")
{
// The submit button
string name = elm.getAttribute("name");
string value = elm.getAttribute("value");
string formId = elm.getAttribute("form");
string formAction = elm.getAttribute("formaction");
if (formId.empty() && _FormOpen) {
formId = _Forms.back().id;
}
insertFormTextButton(name, tooltip, value, _Forms.back().id, "", minWidth, templateName);
insertFormTextButton(name, tooltip, value, formId, formAction, minWidth, templateName);
}
else if (type == "text")
{

@ -57,7 +57,7 @@ namespace NLGUI
// ***************************************************************************
// recursive function to walk html document
void CHtmlParser::parseNode(xmlNode *a_node, CHtmlElement &parent, std::string &styleString, std::vector<std::string> &links) const
void CHtmlParser::parseNode(xmlNode *a_node, CHtmlElement &parent, std::vector<std::string> &styles, std::vector<StyleLink> &links) const
{
uint childIndex = 0;
uint element_number;
@ -145,7 +145,9 @@ namespace NLGUI
if (useStyle)
{
parseStyle(node->children, styleString);
std::string style;
parseStyle(node->children, style);
styles.push_back(style);
}
// style tag is kept in dom
}
@ -163,13 +165,14 @@ namespace NLGUI
if (useStyle)
{
links.push_back(elm.getAttribute("href"));
styles.push_back("");
links.push_back(StyleLink(styles.size()-1, elm.getAttribute("href")));
}
// link tag is kept in dom
}
else if (node->children)
{
parseNode(node->children, elm, styleString, links);
parseNode(node->children, elm, styles, links);
// must cleanup nested tags that libxml2 does not fix
// dt without end tag: <dl><dt><dt></dl>
@ -406,7 +409,7 @@ namespace NLGUI
}
// ***************************************************************************
void CHtmlParser::getDOM(std::string htmlString, CHtmlElement &dom, std::string &styleString, std::vector<std::string> &links) const
void CHtmlParser::getDOM(std::string htmlString, CHtmlElement &dom, std::vector<std::string> &styles, std::vector<StyleLink> &links) const
{
htmlParserCtxtPtr parser = htmlCreatePushParserCtxt(NULL, NULL, NULL, 0, NULL, XML_CHAR_ENCODING_UTF8);
if (!parser)
@ -428,8 +431,7 @@ namespace NLGUI
xmlNode *root = xmlDocGetRootElement(parser->myDoc);
if (root)
{
styleString.clear();
parseNode(root, dom, styleString, links);
parseNode(root, dom, styles, links);
}
else
{

@ -2571,8 +2571,8 @@ bool CFile::createDirectory(const std::string &filename)
#ifdef NL_OS_WINDOWS
return _wmkdir(nlUtf8ToWide(filename)) == 0;
#else
// Set full permissions....
return mkdir(filename.c_str(), 0xFFFF)==0;
// set rwxrwxr-x permissions
return mkdir(filename.c_str(), S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IXOTH)==0;
#endif
}
@ -2810,7 +2810,17 @@ bool CFile::setRWAccess(const std::string &filename)
if (access (filename.c_str(), F_OK) == 0)
{
// try to set the read/write access
if (chmod (filename.c_str(), S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IWGRP|S_IXGRP|S_IROTH|S_IWOTH|S_IXOTH) == -1)
// rw-rw-r--
mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH;
// set +x only for directory
// rwxrwxr-x
if (CFile::isDirectory(filename))
{
mode |= S_IXUSR|S_IXGRP|S_IXOTH;
}
if (chmod (filename.c_str(), mode) == -1)
{
if (INelContext::getInstance().getAlreadyCreateSharedAmongThreads())
{
@ -2831,6 +2841,34 @@ bool CFile::setRWAccess(const std::string &filename)
return true;
}
bool CFile::setExecutable(const std::string &filename)
{
#ifndef NL_OS_WINDOWS
struct stat buf;
if (stat(filename.c_str (), &buf) == 0)
{
mode_t mode = buf.st_mode | S_IXUSR | S_IXGRP | S_IXOTH;
if (chmod(filename.c_str(), mode) == -1)
{
if (INelContext::getInstance().getAlreadyCreateSharedAmongThreads())
{
nlwarning ("PATH: Can't set +x flag on file '%s': %d %s", filename.c_str(), errno, strerror(errno));
}
return false;
}
}
else
{
if (INelContext::getInstance().getAlreadyCreateSharedAmongThreads())
{
nlwarning("PATH: Can't access file '%s': %d %s", filename.c_str(), errno, strerror(errno));
}
return false;
}
#endif
return true;
}
bool CFile::deleteFile(const std::string &filename)
{
setRWAccess(filename);

@ -51,7 +51,7 @@ int main(int argc, char **argv)
printf("---------\n");
for(k = 0; k < ig._InstancesInfos.size(); ++k)
{
printf("instance %s : x = %.1f, y = %.1f, z = %.1f, sx = %.1f, sy = %.1f, sz = %.1f\n", ig._InstancesInfos[k].Name.c_str(), ig._InstancesInfos[k].Pos.x + gpos.x, ig._InstancesInfos[k].Pos.y + gpos.y, ig._InstancesInfos[k].Pos.z + gpos.z, ig._InstancesInfos[k].Scale.x, ig._InstancesInfos[k].Scale.y, ig._InstancesInfos[k].Scale.z);
printf("instance %s : x = %.1f, y = %.1f, z = %.1f, sx = %.1f, sy = %.1f, sz = %.1f, a = %.1f\n", ig._InstancesInfos[k].Name.c_str(), ig._InstancesInfos[k].Pos.x + gpos.x, ig._InstancesInfos[k].Pos.y + gpos.y, ig._InstancesInfos[k].Pos.z + gpos.z, ig._InstancesInfos[k].Scale.x, ig._InstancesInfos[k].Scale.y, ig._InstancesInfos[k].Scale.z, ig._InstancesInfos[k].Rot.getAngle());
}
printf("\n");
printf("Lights\n");

@ -12,6 +12,10 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
#ifndef MAX_PRODUCT_YEAR_NUMBER
#define MAX_PRODUCT_YEAR_NUMBER MAX_VERSION_MAJOR
#endif
#ifdef _DEBUG
#define NL_FILEEXT "_d"
#else

@ -12,6 +12,10 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
#ifndef MAX_PRODUCT_YEAR_NUMBER
#define MAX_PRODUCT_YEAR_NUMBER MAX_VERSION_MAJOR
#endif
#ifdef _DEBUG
#define NL_FILEEXT "_d"
#else

@ -32,6 +32,11 @@ using namespace NLMISC;
// CRTWorld
// ***********************************************************************************************
std::map<INode *, std::pair<NL3D::CMesh::CMeshBuild *, NL3D::CMeshBase::CMeshBaseBuild *>> CRTWorld::s_WorldCache;
std::map<INode *, NLMISC::CAABBox> CRTWorld::s_WorldCacheAABBox;
INode *CRTWorld::s_WorldCacheRoot;
std::string CRTWorld::s_WorldCacheFile;
// -----------------------------------------------------------------------------------------------
CRTWorld::CRTWorld (bool errorInDialog, bool view, bool absolutePath, Interface *ip, std::string errorTitle, CExportNel *exp)
{
@ -351,22 +356,33 @@ void CRTWorld::testCell (CRGBAF &retValue, SGridCell &cell, CVector &vLightPos,
void CRTWorld::addNode (INode *pNode, vector< CMesh::CMeshBuild* > &Meshes, vector< CMeshBase::CMeshBaseBuild* > &MeshesBase,
vector< INode* > &INodes, vector<SLightBuild> &AllLights, const set<INode*> &excludeNode, TimeValue tvTime)
{
if (! RPO::isZone (*pNode, tvTime) )
if (CExportNel::isMesh (*pNode, tvTime))
if (!RPO::isZone(*pNode, tvTime)
&& CExportNel::isMesh(*pNode, tvTime))
{
// Nel export
CExportNel exportNel (_ErrorInDialog, _View, true, _Ip, _ErrorTitle, NULL);
nlassert(_Ip->GetRootNode() == s_WorldCacheRoot);
CAABBox aabbox;
exportNel.buildMeshAABBox(*pNode, aabbox, tvTime);
aabbox.setCenter(aabbox.getCenter()+GlobalTrans);
std::map<INode *, CAABBox>::iterator aabboxIt = s_WorldCacheAABBox.find(pNode);
if (aabboxIt == s_WorldCacheAABBox.end())
{
CExportNel exportNel(_ErrorInDialog, _View, true, _Ip, _ErrorTitle, NULL);
exportNel.buildMeshAABBox(*pNode, aabbox, tvTime);
s_WorldCacheAABBox[pNode] = aabbox;
}
else
{
// FIXME: This breaks repeated exports while the file is open and being changed!!! Not an issue for now
aabbox = aabboxIt->second;
}
aabbox.setCenter(aabbox.getCenter() + GlobalTrans);
// Not an excluded node ?
bool bInteract = false;
if (excludeNode.find (pNode) == excludeNode.end())
if (excludeNode.find(pNode) == excludeNode.end())
{
for( uint32 i = 0; i < AllLights.size(); ++i )
for (uint32 i = 0; i < AllLights.size(); ++i)
{
if( isInteractionWithLight (AllLights[i], aabbox))
if (isInteractionWithLight(AllLights[i], aabbox)) // FIXME: This is always true with sunlight!
{
bInteract = true;
break;
@ -374,25 +390,41 @@ void CRTWorld::addNode (INode *pNode, vector< CMesh::CMeshBuild* > &Meshes, vec
}
}
if( bInteract )
if (bInteract)
{
int nAccelType = CExportNel::getScriptAppData (pNode, NEL3D_APPDATA_ACCEL, 32);
if ((nAccelType&3) == 0) // If not an accelerator
int nAccelType = CExportNel::getScriptAppData(pNode, NEL3D_APPDATA_ACCEL, 32);
if ((nAccelType & 3) == 0) // If not an accelerator
{
nlassert(_Ip->GetRootNode() == s_WorldCacheRoot);
CMesh::CMeshBuild *pMB;
CMeshBase::CMeshBaseBuild *pMBB;
pMB = exportNel.createMeshBuild ( *pNode, tvTime, pMBB);
if( pMBB->bCastShadows )
std::map<INode *, std::pair<NL3D::CMesh::CMeshBuild *, NL3D::CMeshBase::CMeshBaseBuild *>>::iterator buildIt = s_WorldCache.find(pNode);
if (buildIt == s_WorldCache.end())
{
Meshes.push_back( pMB );
MeshesBase.push_back( pMBB );
INodes.push_back( pNode );
CExportNel exportNel(_ErrorInDialog, _View, true, _Ip, _ErrorTitle, NULL);
pMB = exportNel.createMeshBuild(*pNode, tvTime, pMBB);
if (!pMBB->bCastShadows)
{
delete pMB; // No interaction so delete the mesh
pMB = NULL;
delete pMBB; // No interaction so delete the mesh
pMBB = NULL;
}
s_WorldCache[pNode] = std::make_pair(pMB ? new CMesh::CMeshBuild(*pMB) : NULL, pMBB ? new CMeshBase::CMeshBaseBuild(*pMBB) : NULL);
}
else
{
delete pMB; // No interaction so delete the mesh
delete pMBB; // No interaction so delete the mesh
// FIXME: This breaks repeated exports while the file is open and being changed!!! Not an issue for now
pMB = buildIt->second.first ? new CMesh::CMeshBuild(*buildIt->second.first) : NULL;
pMBB = buildIt->second.second ? new CMeshBase::CMeshBaseBuild(*buildIt->second.second) : NULL;
}
if (pMBB) // Implies pMBB->bCastShadows
{
Meshes.push_back(pMB);
MeshesBase.push_back(pMBB);
INodes.push_back(pNode);
}
}
}
@ -405,6 +437,20 @@ void CRTWorld::getAllSelectedNode (vector< CMesh::CMeshBuild* > &Meshes,
vector< INode* > &INodes,
vector<SLightBuild> &AllLights, const set<INode*> &excludeNode, const set<INode*> &includeNode)
{
if (_Ip->GetRootNode() != s_WorldCacheRoot || MaxTStrToUtf8(_Ip->GetCurFileName()) != s_WorldCacheFile) // FIXME: This breaks repeated exports while the file is open and being changed!!! Not an issue for now
{
// Erase all cached builds
for (std::map<INode *, std::pair<NL3D::CMesh::CMeshBuild *, NL3D::CMeshBase::CMeshBaseBuild *>>::iterator it(s_WorldCache.begin()), end(s_WorldCache.end()); it != end; ++it)
{
delete it->second.first;
delete it->second.second;
}
s_WorldCache.clear();
s_WorldCacheAABBox.clear();
s_WorldCacheRoot = _Ip->GetRootNode();
s_WorldCacheFile = MaxTStrToUtf8(_Ip->GetCurFileName());
}
// Get time
TimeValue tvTime = _Ip->GetTime();
@ -443,6 +489,20 @@ void CRTWorld::getAllNodeInScene (vector< CMesh::CMeshBuild* > &Meshes,
vector<SLightBuild> &AllLights, const set<INode*> &excludeNode,
INode* pNode)
{
if (_Ip->GetRootNode() != s_WorldCacheRoot || MaxTStrToUtf8(_Ip->GetCurFileName()) != s_WorldCacheFile) // FIXME: This breaks repeated exports while the file is open and being changed!!! Not an issue for now
{
// Erase all cached builds
for (std::map<INode *, std::pair<NL3D::CMesh::CMeshBuild *, NL3D::CMeshBase::CMeshBaseBuild *>>::iterator it(s_WorldCache.begin()), end(s_WorldCache.end()); it != end; ++it)
{
delete it->second.first;
delete it->second.second;
}
s_WorldCache.clear();
s_WorldCacheAABBox.clear();
s_WorldCacheRoot = _Ip->GetRootNode();
s_WorldCacheFile = MaxTStrToUtf8(_Ip->GetCurFileName());
}
if( pNode == NULL )
pNode = _Ip->GetRootNode();

@ -131,6 +131,12 @@ class CRTWorld
//vector<SCubeGrid> cgAccel; // One cube grid by light point or spot
//vector<SDirGrid> dirAccel; // One grid by light (directionnal only)
NLMISC::CVector GlobalTrans;
static std::map<INode *, std::pair<NL3D::CMesh::CMeshBuild *, NL3D::CMeshBase::CMeshBaseBuild *>> s_WorldCache;
static std::map<INode *, NLMISC::CAABBox> s_WorldCacheAABBox;
static INode *s_WorldCacheRoot;
static std::string s_WorldCacheFile;
public:
CRTWorld (bool errorInDialog, bool view, bool absolutePath, Interface *ip, std::string errorTitle, CExportNel *exp);

@ -12,6 +12,10 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
#ifndef MAX_PRODUCT_YEAR_NUMBER
#define MAX_PRODUCT_YEAR_NUMBER MAX_VERSION_MAJOR
#endif
#ifdef _DEBUG
#define NL_FILEEXT "_d"
#else

@ -12,6 +12,10 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
#ifndef MAX_PRODUCT_YEAR_NUMBER
#define MAX_PRODUCT_YEAR_NUMBER MAX_VERSION_MAJOR
#endif
#ifdef _DEBUG
#define NL_FILEEXT "_d"
#else

@ -12,6 +12,10 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
#ifndef MAX_PRODUCT_YEAR_NUMBER
#define MAX_PRODUCT_YEAR_NUMBER MAX_VERSION_MAJOR
#endif
#ifdef _DEBUG
#define NL_FILEEXT "_d"
#else

@ -12,6 +12,10 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
#ifndef MAX_PRODUCT_YEAR_NUMBER
#define MAX_PRODUCT_YEAR_NUMBER MAX_VERSION_MAJOR
#endif
#ifdef _DEBUG
#define NL_FILEEXT "_d"
#else

@ -12,6 +12,10 @@ LANGUAGE LANG_ENGLISH, SUBLANG_NEUTRAL
#define STRINGIFY_(x) #x
#define STRINGIFY(x) STRINGIFY_(x)
#ifndef MAX_PRODUCT_YEAR_NUMBER
#define MAX_PRODUCT_YEAR_NUMBER MAX_VERSION_MAJOR
#endif
#ifdef _DEBUG
#define NL_FILEEXT "_d"
#else

@ -95,8 +95,12 @@ cfg.write("\t\"" + CartographerContinent + "\", \n")
cfg.write("};\n")
cfg.write("\n")
cfg.write("SeasonSuffixes = {\n")
for suffix in MultipleTilesPostfix:
cfg.write("\t\"" + suffix + "\", \n")
if CartographerSeasonSuffixes:
for suffix in CartographerSeasonSuffixes:
cfg.write("\t\"" + suffix + "\", \n")
else:
for suffix in MultipleTilesPostfix:
cfg.write("\t\"" + suffix + "\", \n")
cfg.write("};\n")
cfg.write("\n")
cfg.write("InverseZTest = true;\n")

@ -0,0 +1,15 @@
title Ryzom Core: 0_setup.py (RING LANDSCAPE)
0_setup.py --noconf -ipj continents/r2_desert continents/r2_forest continents/r2_jungle continents/r2_lakes continents/r2_roots
title Ryzom Core: 1_export.py (RING LANDSCAPE)
1_export.py -ipj continents/r2_desert continents/r2_forest continents/r2_jungle continents/r2_lakes continents/r2_roots
title Ryzom Core: 2_build.py (RING LANDSCAPE)
2_build.py -ipj continents/r2_desert continents/r2_forest continents/r2_jungle continents/r2_lakes continents/r2_roots
title Ryzom Core: 3_install.py (RING LANDSCAPE)
3_install.py -ipj continents/r2_desert continents/r2_forest continents/r2_jungle continents/r2_lakes continents/r2_roots
title Ryzom Core: a1_worldedit_data.py (RING LANDSCAPE)
a1_worldedit_data.py
title Ryzom Core: b1_client_dev.py (RING LANDSCAPE)
b1_client_dev.py
title Ryzom Core: b2_shard_data.py (RING LANDSCAPE)
b2_shard_data.py
title Ryzom Core: Ready (RING LANDSCAPE)

@ -2,5 +2,8 @@
IF(WITH_LIGO)
IF(WITH_3D)
ADD_SUBDIRECTORY(unbuild_land)
IF(WITH_GEORGES)
ADD_SUBDIRECTORY(unbuild_flora)
ENDIF()
ENDIF()
ENDIF()

@ -0,0 +1,11 @@
FILE(GLOB SRC *.cpp *.h *.rc)
SOURCE_GROUP("" FILES ${SRC})
ADD_EXECUTABLE(nl_unbuild_flora ${SRC})
TARGET_LINK_LIBRARIES(nl_unbuild_flora nel3d nelmisc nelligo nelgeorges)
NL_DEFAULT_PROPS(nl_unbuild_flora "NeL, Tools, Ligo: Unbuild Flora")
NL_ADD_RUNTIME_FLAGS(nl_unbuild_flora)
INSTALL(TARGETS nl_unbuild_flora RUNTIME DESTINATION ${NL_BIN_PREFIX} COMPONENT toolsligo)

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

@ -0,0 +1,42 @@
#include <windows.h>
#include "config.h"
IDI_MAIN_ICON ICON DISCARDABLE "gold_pill.ico"
#ifdef _DEBUG
#define NL_FILEEXT "_d"
#else
#define NL_FILEEXT ""
#endif
VS_VERSION_INFO VERSIONINFO
FILEVERSION NL_VERSION_RC
PRODUCTVERSION NL_VERSION_RC
FILEFLAGSMASK VS_FFI_FILEFLAGSMASK
#ifdef _DEBUG
FILEFLAGS VS_FF_DEBUG
#else
FILEFLAGS 0x0L
#endif
FILEOS VOS_NT_WINDOWS32
FILETYPE VFT_APP
FILESUBTYPE 0x0L
BEGIN
BLOCK "StringFileInfo"
BEGIN
BLOCK "040904b0"
BEGIN
VALUE "CompanyName", AUTHOR
VALUE "FileDescription", "NeL Unbuild Flora"
VALUE "FileVersion", NL_VERSION
VALUE "LegalCopyright", COPYRIGHT
VALUE "OriginalFilename", "nl_unbuild_flora" NL_FILEEXT ".exe"
VALUE "ProductName", "NeL Tools"
VALUE "ProductVersion", NL_PRODUCT_VERSION
END
END
BLOCK "VarFileInfo"
BEGIN
VALUE "Translation", 0x9, 1200
END
END

@ -0,0 +1,442 @@
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2019 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as
// published by the Free Software Foundation, either version 3 of the
// License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
//
// This utility is intended to rescue a lost flora .primitive file.
// It only recovers the generated flora positions, it cannot recover
// the flora zones.
//
// Author: Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
// #include "../../3d/zone_lib/zone_utility.h"
#include <iostream>
#include <nel/misc/types_nl.h>
#include <nel/misc/file.h>
#include <nel/misc/common.h>
#include <nel/misc/cmd_args.h>
#include <nel/misc/string_view.h>
#include <nel/georges/u_form.h>
#include <nel/georges/u_form_elm.h>
#include <nel/georges/u_form_loader.h>
#include <nel/3d/scene_group.h>
#include <iostream>
#include <fstream>
#include <vector>
#include <list>
#include <map>
using namespace std;
using namespace NLMISC;
using namespace NL3D;
using namespace NLGEORGES;
//using namespace NLLIGO;
namespace /* anonymous */
{
/*
Process:
- Load all .plant sheets, map from .shape to .plant and bounding radius (Reference: prim_export, main.cpp)
- Load all source igs (Reference: ig_info, ig_info.cpp)
- Load all reference igs, remove matching entries from source igs
- Generate primitives
*/
std::string s_DfnDir; /* R:\leveldesign\DFN */
std::string s_LeveldesignDir; /* R:\leveldesign\game_elem\plant\ecosystem */
std::string s_SourceDir; /* R:\reference\2008_july\data\r2_desert2 */
std::string s_ReferenceDir; /* R:\pipeline\export\continents\r2_desert\zone_lighted_ig_land */
std::string s_PrimitiveFile; /* R:\graphics\primitive\r2_desert\r2_desert.primitive */
/*
Debug arguments:
"R:\leveldesign\DFN" "R:\leveldesign\game_elem\plant\ecosystem" "R:\reference\2008_july\data\r2_desert2" "R:\pipeline\export\continents\r2_desert\zone_lighted_ig_land" "R:\graphics\primitive\r2_desert\r2_desert.primitive"
"R:\leveldesign\DFN" "R:\leveldesign\game_elem\plant\ecosystem" "R:\reference\2008_july\data\r2_forest2" "R:\pipeline\export\continents\r2_forest\zone_lighted_ig_land" "R:\graphics\primitive\r2_forest\r2_forest.primitive"
"R:\leveldesign\DFN" "R:\leveldesign\game_elem\plant\ecosystem" "R:\reference\2008_july\data\r2_jungle2" "R:\pipeline\export\continents\r2_jungle\zone_lighted_ig_land" "R:\graphics\primitive\r2_jungle\r2_jungle.primitive"
"R:\leveldesign\DFN" "R:\leveldesign\game_elem\plant\ecosystem" "R:\reference\2008_july\data\r2_lakes2" "R:\pipeline\export\continents\r2_lakes\zone_lighted_ig_land" "R:\graphics\primitive\r2_lakes\r2_lakes.primitive"
"R:\leveldesign\DFN" "R:\leveldesign\game_elem\plant\ecosystem" "R:\reference\2008_july\data\r2_roots2" "R:\pipeline\export\continents\r2_roots\zone_lighted_ig_land" "R:\graphics\primitive\r2_roots\r2_roots.primitive"
*/
struct CPoint
{
std::string ZoneLwr;
CVector Pos; /* Position, height not necessarily specified (X="26218.738281" Y="-1092.078979" Z="0.000000") */
float Angle; /* (2.827213) */
float Scale; /* Scale (0.643217) */
std::string Shape;
bool Plant;
std::string Form; /* (FY_S2_savantree_B) */
std::string Name; /* Generated unique name (ilot_008_savantree 13) */
float Radius; /* Bounding radius (calculated from plant sheet and scale) (0.450252) */
};
/*
<CHILD TYPE="CPrimPoint">
<PT X="26060.041016" Y="-1033.684692" Z="0.000000"/>
<ANGLE VALUE="4.806300"/>
<PROPERTY TYPE="string">
<NAME>class</NAME>
<STRING>prim</STRING>
</PROPERTY>
<PROPERTY TYPE="string">
<NAME>form</NAME>
<STRING>FY_S2_savantree_B</STRING>
</PROPERTY>
<PROPERTY TYPE="string">
<NAME>layer</NAME>
<STRING>0</STRING>
</PROPERTY>
<PROPERTY TYPE="string">
<NAME>name</NAME>
<STRING>ilot_008_savantree 15</STRING>
</PROPERTY>
<PROPERTY TYPE="string">
<NAME>radius</NAME>
<STRING>0.784730</STRING>
</PROPERTY>
<PROPERTY TYPE="string">
<NAME>scale</NAME>
<STRING>1.121043</STRING>
</PROPERTY>
</CHILD>
*/
/*
* <?xml version="1.0"?>
<PRIMITIVES VERSION="1">
<ROOT_PRIMITIVE TYPE="CPrimNode">
<ALIAS LAST_GENERATED="0"/>
<CHILD TYPE="CPrimNode">
<PROPERTY TYPE="string">
<NAME>class</NAME>
<STRING>flora</STRING>
</PROPERTY>
<PROPERTY TYPE="string">
<NAME>name</NAME>
<STRING>R2 flora 1</STRING>
</PROPERTY>
<CHILD ... />
<CHILD ... />
<CHILD ... />
...
</CHILD>
</ROOT_PRIMITIVE>
</PRIMITIVES>
*/
/*
instance fy_s2_savantree_c.shape : x = 23031.2, y = -1269.2, z = 75.8, sx = 0.5, sy = 0.5, sz = 0.5
instance fy_s2_savantree_c.shape : x = 22906.6, y = -1148.1, z = 79.6, sx = 0.6, sy = 0.6, sz = 0.6
*/
struct CPlant
{
std::string Form;
std::string Shape;
float Radius;
};
std::map<std::string, CPlant> s_ShapeToForm;
std::list<CPoint> s_Instances;
bool loadLeveldesign()
{
UFormLoader *formLoader = UFormLoader::createLoader();
struct CRel0 { CRel0(UFormLoader *v) : m(v) {} ~CRel0() { UFormLoader::releaseLoader(m); } UFormLoader *m; } rel0(formLoader);
std::vector<std::string> plants;
CPath::getFileList("plant", plants);
for (std::vector<std::string>::iterator it(plants.begin()), end(plants.end()); it != end; ++it)
{
printf("%s\n", nlUtf8ToMbcs(*it));
CSmartPtr <UForm> form = formLoader->loadForm(*it);
if (!form)
continue;
CPlant plant;
plant.Form = toLowerAscii(*it);
if (!form->getRootNode().getValueByName(plant.Shape, "3D.Shape"))
continue;
if (plant.Shape.empty())
{
if (!form->getRootNode().getValueByName(plant.Shape, "3D.SpringFX.FXName"))
continue;
}
if (plant.Shape.empty())
continue;
(void)plant.Shape.c_str();
toLowerAscii(&plant.Shape[0]);
if (!form->getRootNode().getValueByName(plant.Radius, "3D.Bounding Radius"))
continue;
printf(" = '%s', %f\n", nlUtf8ToMbcs(plant.Shape), plant.Radius);
s_ShapeToForm[plant.Shape] = plant;
}
return true;
}
bool loadInstances()
{
std::vector<std::string> igs;
CPath::getPathContent(s_SourceDir, true, false, true, igs);
for (std::vector<std::string>::iterator it(igs.begin()), end(igs.end()); it != end; ++it)
{
if (CFile::getExtension(*it) != nlstr("ig"))
continue;
printf("%s\n", nlUtf8ToMbcs(*it));
CInstanceGroup ig;
CIFile inputStream;
if (!inputStream.open(*it))
{
nlwarning("Unable to open %s\n", (*it).c_str());
return false;
}
ig.serial(inputStream);
CVector gpos = ig.getGlobalPos();
if (gpos.x != 0.0f || gpos.y != 0.0f || gpos.z != 0.0f)
{
nlwarning("Invalid global pos: %f, %f, %f", gpos.x, gpos.y, gpos.z);
return false;
}
string zoneLwr = toLowerAscii(CFile::getFilenameWithoutExtension(*it));
for (ptrdiff_t i = 0; i < (ptrdiff_t)ig._InstancesInfos.size(); ++i)
{
CInstanceGroup::CInstance &info = ig._InstancesInfos[i];
CPoint instance;
instance.Pos = info.Pos;
instance.Angle = info.Rot.getAngle();
instance.Scale = info.Scale.z;
instance.Shape = toLowerAscii(info.Name);
printf("%s\n", nlUtf8ToMbcs(instance.Shape));
std::map<std::string, CPlant>::iterator formIt = s_ShapeToForm.find(instance.Shape);
if (formIt != s_ShapeToForm.end())
{
instance.Form = formIt->second.Form;
instance.Name = CFile::getFilenameWithoutExtension(instance.Form) + nlstr("_") + zoneLwr + nlstr("_") + toString(i);
instance.Radius = instance.Scale * formIt->second.Radius;
printf(" = %f, %f, %f, %f, %f, '%s', '%s', %f\n", instance.Pos.x, instance.Pos.y, instance.Pos.z, instance.Angle, instance.Scale, nlUtf8ToMbcs(instance.Form), nlUtf8ToMbcs(instance.Name), instance.Radius);
instance.Plant = true;
}
else
{
instance.Plant = false;
}
s_Instances.push_back(instance);
}
}
return true;
}
bool eraseReference()
{
std::vector<std::string> igs;
CPath::getPathContent(s_ReferenceDir, true, false, true, igs);
for (std::vector<std::string>::iterator it(igs.begin()), end(igs.end()); it != end; ++it)
{
if (CFile::getExtension(*it) != nlstr("ig"))
continue;
printf("%s\n", nlUtf8ToMbcs(*it));
CInstanceGroup ig;
CIFile inputStream;
if (!inputStream.open(*it))
{
nlwarning("Unable to open %s\n", (*it).c_str());
return false;
}
ig.serial(inputStream);
CVector gpos = ig.getGlobalPos();
if (gpos.x != 0.0f || gpos.y != 0.0f || gpos.z != 0.0f)
{
nlwarning("Invalid global pos: %f, %f, %f", gpos.x, gpos.y, gpos.z);
return false;
}
string zoneLwr = toLowerAscii(CFile::getFilenameWithoutExtension(*it));
for (ptrdiff_t i = 0; i < (ptrdiff_t)ig._InstancesInfos.size(); ++i)
{
CInstanceGroup::CInstance &info = ig._InstancesInfos[i];
string shape = toLowerAscii(info.Name);
printf("%s\n", nlUtf8ToMbcs(shape));
bool erased = false;
for (std::list<CPoint>::iterator it(s_Instances.begin()), end(s_Instances.end()); it != end; ++it)
{
const CPoint &instance = *it;
if (instance.Pos.x == info.Pos.x
&& instance.Pos.y == info.Pos.y
&& instance.Shape == shape)
{
printf(" = Found and erased\n");
s_Instances.erase(it);
erased = true;
break;
}
}
if (!erased)
printf(" = NOT FOUND!\n");
}
}
return true;
}
bool eraseNonPlants()
{
for (std::list<CPoint>::iterator it(s_Instances.begin()), end(s_Instances.end()); it != end;)
{
const CPoint &instance = *it;
if (!instance.Plant)
{
printf("Erase '%s' because it's not a plant!\n", nlUtf8ToMbcs(instance.Shape));
std::list<CPoint>::iterator nextIt = it;
++nextIt;
s_Instances.erase(it);
it = nextIt;
}
else
{
++it;
}
}
return true;
}
bool writeFlora()
{
ofstream fo;
#ifdef NL_OS_WINDOWS
fo.open(utf8ToWide(s_PrimitiveFile));
#else
fo.open(s_PrimitiveFile);
#endif
fo << "<?xml version=\"1.0\"?>\n";
fo << "<PRIMITIVES VERSION=\"1\">\n";
fo << " <ROOT_PRIMITIVE TYPE=\"CPrimNode\">\n";
fo << " <ALIAS LAST_GENERATED=\"0\"/>\n";
fo << " <CHILD TYPE=\"CPrimNode\">\n";
fo << " <PROPERTY TYPE=\"string\">\n";
fo << " <NAME>class</NAME>\n";
fo << " <STRING>flora</STRING>\n";
fo << " </PROPERTY>\n";
fo << " <PROPERTY TYPE=\"string\">\n";
fo << " <NAME>name</NAME>\n";
fo << " <STRING>" << CFile::getFilenameWithoutExtension(s_PrimitiveFile) << "_flora</STRING>\n";
fo << " </PROPERTY>\n";
for (std::list<CPoint>::iterator it(s_Instances.begin()), end(s_Instances.end()); it != end; ++it)
{
const CPoint &instance = *it;
fo << " <CHILD TYPE=\"CPrimPoint\">\n";
fo << " <PT X=\"" << instance.Pos.x << "\" Y=\"" << instance.Pos.y << "\" Z=\"0.000000\"/>\n";
fo << " <ANGLE VALUE=\"" << instance.Angle << "\"/>\n";
fo << " <PROPERTY TYPE=\"string\">\n";
fo << " <NAME>class</NAME>\n";
fo << " <STRING>prim</STRING>\n";
fo << " </PROPERTY>\n";
fo << " <PROPERTY TYPE=\"string\">\n";
fo << " <NAME>form</NAME>\n";
fo << " <STRING>" << CFile::getFilenameWithoutExtension(instance.Form) << "</STRING>\n";
fo << " </PROPERTY>\n";
fo << " <PROPERTY TYPE=\"string\">\n";
fo << " <NAME>layer</NAME>\n";
fo << " <STRING>0</STRING>\n";
fo << " </PROPERTY>\n";
fo << " <PROPERTY TYPE=\"string\">\n";
fo << " <NAME>name</NAME>\n";
fo << " <STRING>" << instance.Name << "</STRING>\n";
fo << " </PROPERTY>\n";
fo << " <PROPERTY TYPE=\"string\">\n";
fo << " <NAME>radius</NAME>\n";
fo << " <STRING>" << instance.Radius << "</STRING>\n";
fo << " </PROPERTY>\n";
fo << " <PROPERTY TYPE=\"string\">\n";
fo << " <NAME>scale</NAME>\n";
fo << " <STRING>" << instance.Scale << "</STRING>\n";
fo << " </PROPERTY>\n";
fo << " </CHILD>\n";
}
fo << " </CHILD>\n";
fo << " </ROOT_PRIMITIVE>\n";
fo << "</PRIMITIVES>\n";
printf("Generated:\n%s\n", nlUtf8ToMbcs(s_PrimitiveFile));
return true;
}
bool unbuildFlora()
{
CPath::addSearchPath(s_DfnDir, true, false);
CPath::addSearchPath(s_LeveldesignDir, true, false);
return loadLeveldesign()
&& loadInstances()
&& eraseReference()
&& eraseNonPlants()
&& writeFlora();
}
bool unbuildFlora(NLMISC::CCmdArgs &args)
{
s_DfnDir = args.getAdditionalArg("dfn")[0];
s_LeveldesignDir = args.getAdditionalArg("leveldesign")[0];
s_SourceDir = args.getAdditionalArg("source")[0];
s_ReferenceDir = args.getAdditionalArg("reference")[0];
s_PrimitiveFile = args.getAdditionalArg("primitive")[0];
return unbuildFlora();
}
} /* anonymous namespace */
int main(int argc, char **argv)
{
NLMISC::CApplicationContext myApplicationContext;
NLMISC::CCmdArgs args;
args.addAdditionalArg("dfn", "Input folder with DFN");
args.addAdditionalArg("leveldesign", "Input folder with plant sheets");
args.addAdditionalArg("source", "Input folder with IGs containing flora");
args.addAdditionalArg("reference", "Input folder with IGs missing flora");
args.addAdditionalArg("primitive", "Output flora primitive file");
if (!args.parse(argc, argv))
{
return EXIT_FAILURE;
}
if (!unbuildFlora(args))
{
args.displayHelp();
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
/* end of file */

@ -138,6 +138,8 @@ int main(int argc, char **argv)
args.addArg("o", "output", "destination", "Output directory or file");
args.addArg("i", "if", "wildcard", "Add the file if it matches the wilcard (at least one 'if' conditions must be met for a file to be adding)", false);
args.addArg("n", "ifnot", "wildcard", "Add the file if it doesn't match the wilcard (all the 'ifnot' conditions must be met for a file to be adding)", false);
args.addArg("", "list-verbose", "", "List files using 'pos size name' format");
args.addArg("", "extract", "name", "Extract file(s) from BNP into --output");
args.addAdditionalArg("input", "Input directory or BNP file depending on command");
if (!args.parse(argc, argv)) return 1;
@ -236,6 +238,60 @@ int main(int argc, char **argv)
return 0;
}
if (args.haveLongArg("list-verbose"))
{
gBNPHeader.BigFileName = args.getAdditionalArg("input").front();
// Read header of BNP file
if (!gBNPHeader.readHeader()) return -1;
for (uint i = 0; i < gBNPHeader.SFiles.size(); ++i)
{
printf("%u %u %s\n", gBNPHeader.SFiles[i].Pos, gBNPHeader.SFiles[i].Size, gBNPHeader.SFiles[i].Name.c_str());
}
return 0;
}
// --extract <name>
if (args.haveLongArg("extract") && !args.getLongArg("extract").empty())
{
std::string bnpName = args.getAdditionalArg("input").front();
CBigFile::getInstance().add(bnpName, BF_ALWAYS_OPENED);
// Output directory or filename
if (!args.haveArg("o") || args.getArg("o").empty())
{
nlerror("Output file or directory not set");
}
std::string srcName = args.getLongArg("extract").front();
std::string dstName = args.getArg("o").front();
if (CFile::fileExists(dstName) && CFile::isDirectory(dstName))
{
dstName += "/" + srcName;
}
CIFile inFile;
// bnpName without path
if (!inFile.open(CFile::getFilename(bnpName) + "@" + srcName))
{
nlerror("Unable to open '%s' for reading", inFile.getStreamName().c_str());
}
COFile outFile;
if (!outFile.open(dstName))
{
nlerror("Unable to open '%s' for writing", outFile.getStreamName().c_str());
}
std::string buf;
inFile.readAll(buf);
outFile.serialBuffer((uint8 *)&buf[0], buf.size());
return 0;
}
args.displayHelp();
return -1;
}

@ -1035,6 +1035,7 @@ void CPatchManager::executeBatchFile()
// make script executable
CFile::setRWAccess(batchFilename);
CFile::setExecutable(batchFilename);
// append login, password and shard
if (!LoginLogin.empty())

@ -191,7 +191,8 @@ struct CClientPatcherTranslations : public NLMISC::CI18N::ILoadProxy
};
// hardcoded URL to not depend on external files
static const std::string PatchUrl = RYZOM_CLIENT_PATCH_URL; // "https://cdn.ryzom.dev/open/patch";
static const std::string DefaultPatchUrl = RYZOM_CLIENT_PATCH_URL; // "https://cdn.ryzom.dev/open/patch";
static const std::string DefaultAppName = RYZOM_CLIENT_APP_NAME; // "default"
int main(int argc, char *argv[])
{
@ -200,10 +201,8 @@ int main(int argc, char *argv[])
Args.setVersion(getDisplayVersion());
Args.setDescription("Ryzom client");
Args.addArg("p", "patch", "patch", "Name of the file to use tp xdelta the source file");
Args.addArg("s", "source", "source", "Name of source file to xdelta with patch file");
Args.addArg("d", "destination", "destination", "Name of destination operation (patch or unpack)");
Args.addArg("u", "unpack", "unpack", "Name of bnp file to unpack");
Args.addArg("", "url", "PatchUrl", "Patch server url, ie 'https://dl.ryzom.com/patch_live'");
Args.addArg("", "app", "Application", "Patch application name for version file, ie 'ryzom_live' requests ryzom_live.version from PatchUrl");
if (!Args.parse(argc, argv)) return 1;
@ -269,14 +268,33 @@ int main(int argc, char *argv[])
// now translations are read, we don't need it anymore
delete trans;
// create minimal client.cfg file in memory for patcher
{
CConfigFile::CVar patchUrl;
patchUrl.forceAsString(DefaultPatchUrl);
if (Args.haveLongArg("url") && !Args.getLongArg("url").empty())
patchUrl.forceAsString(Args.getLongArg("url").front());
CConfigFile::CVar appName;
appName.forceAsString(DefaultAppName);
if (Args.haveLongArg("app") && !Args.getLongArg("app").empty())
appName.forceAsString(Args.getLongArg("app").front());
ClientCfg.ConfigFile.insertVar("PatchUrl", patchUrl);
ClientCfg.ConfigFile.insertVar("Application", appName);
}
//
Args.displayVersion();
printf("\n");
printf("Checking %s files to patch...\n", convert(CI18N::get("TheSagaOfRyzom")).c_str());
printf("Using '%s/%s.version'\n", ClientCfg.ConfigFile.getVar("PatchUrl").asString().c_str(),
ClientCfg.ConfigFile.getVar("Application").asString().c_str());
// use PatchUrl
vector<string> patchURLs;
pPM->init(patchURLs, PatchUrl, "");
pPM->init(patchURLs, ClientCfg.ConfigFile.getVar("PatchUrl").asString(), "");
pPM->startCheckThread(true /* include background patchs */);
string state;
@ -356,6 +374,7 @@ int main(int argc, char *argv[])
try
{
// move downloaded files to final location
// batch file will not be created
pPM->createBatchFile(pPM->getDescFile(), false, false);
CFile::createEmptyFile("show_eula");
@ -386,17 +405,20 @@ int main(int argc, char *argv[])
printError(convert(CI18N::get("uiErrPatchApply")) + " " + error);
return 1;
}
pPM->executeBatchFile();
}
/*
// Start Scanning
pPM->startScanDataThread();
// request to stop the thread
pPM->askForStopScanDataThread();
*/
// upgd_nl.sh will normally take care of the permissions
//
// for linux/macOS (no-op on windows)
// Set for current executable (might be 'dev' version),
// and also 'ryzom_client_patcher' directly (from patched files)
CFile::setExecutable(Args.getProgramPath() + Args.getProgramName());
CFile::setExecutable("ryzom_client_patcher");
// other
CFile::setExecutable("crash_report");
CFile::setExecutable("ryzom_client");
CFile::setExecutable("ryzom_installer_qt");
CFile::setExecutable("ryzom_configuration_qt");
return 0;
}

@ -33,6 +33,7 @@
#include <nel/misc/progress_callback.h>
#include <nel/misc/random.h>
#include <nel/misc/common.h>
#include <nel/misc/wang_hash.h>
#include <nel/3d/u_material.h>
#include <nel/3d/u_driver.h>
@ -1369,6 +1370,7 @@ void CScreenshotIslands::buildIslandsTextures()
// Create and load landscape
ULandscape * landscape = scene->createLandscape();
landscape->setThreshold(0.0005);
landscape->setTileNear(10000);
if(_InverseZTest)
{
landscape->setZFunc(UMaterial::greaterequal);
@ -1464,7 +1466,7 @@ void CScreenshotIslands::buildIslandsTextures()
vector<string> zonesAdded;
vector<string> zonesRemoved;
IProgressCallback progress;
landscape->refreshAllZonesAround(camera.getMatrix().getPos(), 1000, zonesAdded, zonesRemoved, progress);
landscape->refreshAllZonesAround(camera.getMatrix().getPos(), 2000, zonesAdded, zonesRemoved, progress);
if(_Vegetation)
{
LandscapeIGManager.unloadArrayZoneIG(zonesRemoved);
@ -1644,8 +1646,8 @@ void CScreenshotIslands::buildIslandsTextures()
// little tga
bitmapLittle.resample(bitmapLittle.getWidth()/10, bitmapLittle.getHeight()/10);
if(!isPowerOf2(bitmapLittle.getWidth()) || !isPowerOf2(bitmapLittle.getHeight()) )
bitmapLittle.resample(bitmapLittle.getWidth() / 20, bitmapLittle.getHeight() / 20);
if (!isPowerOf2(bitmapLittle.getWidth()) || !isPowerOf2(bitmapLittle.getHeight()))
{
uint pow2w = NLMISC::raiseToNextPowerOf2(bitmapLittle.getWidth());
uint pow2h = NLMISC::raiseToNextPowerOf2(bitmapLittle.getHeight());
@ -1871,15 +1873,19 @@ void CScreenshotIslands::buildBackTextureHLS(const std::string & islandName, con
{
_BackColor = maxColor;
CRandom randomGenerator;
std::string islandNameLwr = toLowerAscii(islandName);
uint32_t seed = 0;
for (ptrdiff_t i = 0; i < (ptrdiff_t)islandNameLwr.size(); ++i)
seed += wangHash(seed ^ islandNameLwr[i]);
uint8 * backPixels = &(_BackBitmap.getPixels(0)[0]);
uint i = 0;
for(uint x=0; x<_BackBitmap.getWidth(); x++)
{
for(uint y=0; y<_BackBitmap.getHeight(); y++)
for(uint y=0; y<_BackBitmap.getHeight(); y++, i++)
{
sint32 randomVal = randomGenerator.rand(colorsNb-1);
sint32 randomVal = wangHash(seed ^ i) % colorsNb;
const CRGBA & color = sortedColors[randomVal];
*backPixels = (uint8) color.R;

Loading…
Cancel
Save