From 23110247de0c8f637014480ef146a9e540213464 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Tue, 24 Nov 2020 03:58:29 +0800 Subject: [PATCH 01/15] Script for rebuilding ring landscapes --- nel/tools/build_gamedata/ring_landscape_dev.bat | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 nel/tools/build_gamedata/ring_landscape_dev.bat diff --git a/nel/tools/build_gamedata/ring_landscape_dev.bat b/nel/tools/build_gamedata/ring_landscape_dev.bat new file mode 100644 index 000000000..2bcac4dc1 --- /dev/null +++ b/nel/tools/build_gamedata/ring_landscape_dev.bat @@ -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) From 47d6e0909947bd234df1a9154463139a3e1fbfdb Mon Sep 17 00:00:00 2001 From: kaetemi Date: Wed, 25 Nov 2020 07:50:31 +0800 Subject: [PATCH 02/15] Tool for reverse building flora primitive, load plants, ryzom/ryzomcore#621 --- nel/tools/ligo/CMakeLists.txt | 3 + nel/tools/ligo/unbuild_flora/CMakeLists.txt | 11 + nel/tools/ligo/unbuild_flora/gold_pill.ico | Bin 0 -> 3638 bytes nel/tools/ligo/unbuild_flora/main.rc | 42 +++ .../ligo/unbuild_flora/unbuild_flora.cpp | 259 ++++++++++++++++++ 5 files changed, 315 insertions(+) create mode 100644 nel/tools/ligo/unbuild_flora/CMakeLists.txt create mode 100644 nel/tools/ligo/unbuild_flora/gold_pill.ico create mode 100644 nel/tools/ligo/unbuild_flora/main.rc create mode 100644 nel/tools/ligo/unbuild_flora/unbuild_flora.cpp diff --git a/nel/tools/ligo/CMakeLists.txt b/nel/tools/ligo/CMakeLists.txt index 9a7f24ebe..230e4c74a 100644 --- a/nel/tools/ligo/CMakeLists.txt +++ b/nel/tools/ligo/CMakeLists.txt @@ -2,5 +2,8 @@ IF(WITH_LIGO) IF(WITH_3D) ADD_SUBDIRECTORY(unbuild_land) + IF(WITH_GEORGES) + ADD_SUBDIRECTORY(unbuild_flora) + ENDIF() ENDIF() ENDIF() diff --git a/nel/tools/ligo/unbuild_flora/CMakeLists.txt b/nel/tools/ligo/unbuild_flora/CMakeLists.txt new file mode 100644 index 000000000..6c9dc99c4 --- /dev/null +++ b/nel/tools/ligo/unbuild_flora/CMakeLists.txt @@ -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) diff --git a/nel/tools/ligo/unbuild_flora/gold_pill.ico b/nel/tools/ligo/unbuild_flora/gold_pill.ico new file mode 100644 index 0000000000000000000000000000000000000000..618b67a5d196bdbdc4d497a3b7ca998b79039677 GIT binary patch literal 3638 zcmeH|zityj5XQf`vv2R8lRF0=!64zvLOcRZ@(47%1EO$G7suZ;o}Ow9KWIF7uW|24qu=jCYmGObHC}wun9t{!&1Sg$ zP6MyLV>})M&yFz~jWC%^fQS2+=cprf1?md?hZP`8`Oj#}K*|8hER?sITv4;NA<$;R zq>3WH(P#z%rJ$%(X!S5zlUP+N zzr|;JJa&1AAFqXdR(y5mKwA%eZ9P`}w)9@{Sn*u(Tk&M^-mm(n@m=v)}3W?H=*(Tyb(EO1J?UWK}aqZWd!Zofe&kK&zR)e`x(xG +#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 diff --git a/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp b/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp new file mode 100644 index 000000000..7aeb404b4 --- /dev/null +++ b/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp @@ -0,0 +1,259 @@ +// NeL - MMORPG Framework +// Copyright (C) 2019 Jan BOON (Kaetemi) +// +// 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 . +// +// 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) + +// #include "../../3d/zone_lib/zone_utility.h" + +#include + +#include +#include +//#include +#include +#include +//#include + +#include +#include +#include + +//#include +//#include +//#include +//#include +//#include +//#include +//#include +#include + +#include +//#include +#include + +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 +- Load all source igs +- 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" + +*/ + +struct CPoint +{ + CVector Pos; /* Position, height not necessarily specified (X="26218.738281" Y="-1092.078979" Z="0.000000") */ + float Angle; /* (2.827213) */ + std::string Form; /* (FY_S2_savantree_B) */ + std::string Name; /* Generated unique name (ilot_008_savantree 13) */ + float Radius; /* Bounding radius (from plant sheet and scale) (0.450252) */ + float Scale; /* Scale (0.643217) */ +}; + +/* + + + + + class + prim + + + form + FY_S2_savantree_B + + + layer + 0 + + + name + ilot_008_savantree 15 + + + radius + 0.784730 + + + scale + 1.121043 + + +*/ + +/* +* + + + + + + class + flora + + + name + R2 flora 1 + + + + + ... + + + +*/ + +/* +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 s_ShapeToForm; + +bool loadLeveldesign() +{ + UFormLoader *formLoader = UFormLoader::createLoader(); + struct CRel0 { CRel0(UFormLoader *v) : m(v) {} ~CRel0() { UFormLoader::releaseLoader(m); } UFormLoader *m; } rel0(formLoader); + + std::vector plants; + CPath::getFileList("plant", plants); + + for (std::vector::iterator it(plants.begin()), end(plants.end()); it != end; ++it) + { + printf("%s\n", (*it).c_str()); + CSmartPtr 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; + plant.Shape.c_str(); + toLowerAscii(&plant.Shape[0]); + if (!form->getRootNode().getValueByName(plant.Radius, "3D.Bounding Radius")) + continue; + printf(" = '%s', %f\n", plant.Shape.c_str(), plant.Radius); + s_ShapeToForm[plant.Shape] = plant; + } + + return true; +} + +bool unbuildFlora() +{ + CPath::addSearchPath(s_DfnDir, true, false); + CPath::addSearchPath(s_LeveldesignDir, true, false); + + if (!loadLeveldesign()) + return false; + + + /* + CInstanceGroup ig; + CIFile inputStream; + if (!inputStream.open(string(argv[1]))) + { + printf("unable to open %s\n", argv[1]); + return -1; + } + */ + + return false; +} + +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 */ From d6fe42f6a0f3012b7a0d62a08d98ab673e34eef2 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Wed, 25 Nov 2020 08:43:19 +0800 Subject: [PATCH 03/15] Load and map instances to plants, ryzom/ryzomcore#621 --- .../ligo/unbuild_flora/unbuild_flora.cpp | 92 ++++++++++++++----- 1 file changed, 70 insertions(+), 22 deletions(-) diff --git a/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp b/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp index 7aeb404b4..5aa411fc2 100644 --- a/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp +++ b/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp @@ -30,6 +30,7 @@ #include #include //#include +#include #include #include @@ -41,16 +42,17 @@ //#include //#include //#include -//#include #include +//#include + #include //#include #include using namespace std; using namespace NLMISC; -//using namespace NL3D; +using namespace NL3D; using namespace NLGEORGES; //using namespace NLLIGO; @@ -60,8 +62,8 @@ namespace /* anonymous */ /* Process: -- Load all .plant sheets, map from .shape to .plant and bounding radius -- Load all source igs +- 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 @@ -83,12 +85,17 @@ Debug arguments: 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) */ + + bool Plant; std::string Form; /* (FY_S2_savantree_B) */ std::string Name; /* Generated unique name (ilot_008_savantree 13) */ - float Radius; /* Bounding radius (from plant sheet and scale) (0.450252) */ - float Scale; /* Scale (0.643217) */ + float Radius; /* Bounding radius (calculated from plant sheet and scale) (0.450252) */ + }; /* @@ -158,6 +165,7 @@ struct CPlant }; std::map s_ShapeToForm; +std::set s_Instances; bool loadLeveldesign() { @@ -185,7 +193,7 @@ bool loadLeveldesign() if (plant.Shape.empty()) continue; plant.Shape.c_str(); - toLowerAscii(&plant.Shape[0]); + (void)toLowerAscii(&plant.Shape[0]); if (!form->getRootNode().getValueByName(plant.Radius, "3D.Bounding Radius")) continue; printf(" = '%s', %f\n", plant.Shape.c_str(), plant.Radius); @@ -195,26 +203,66 @@ bool loadLeveldesign() return true; } -bool unbuildFlora() +bool loadInstances() { - CPath::addSearchPath(s_DfnDir, true, false); - CPath::addSearchPath(s_LeveldesignDir, true, false); - - if (!loadLeveldesign()) - return false; + std::vector igs; + CPath::getPathContent(s_SourceDir, true, false, true, igs); - - /* - CInstanceGroup ig; - CIFile inputStream; - if (!inputStream.open(string(argv[1]))) + for (std::vector::iterator it(igs.begin()), end(igs.end()); it != end; ++it) { - printf("unable to open %s\n", argv[1]); - return -1; + if (CFile::getExtension(*it) != nlstr("ig")) + continue; + printf("%s\n", (*it).c_str()); + 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; + string shape = toLowerAscii(info.Name); + printf("%s\n", shape.c_str()); + std::map::iterator formIt = s_ShapeToForm.find(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, instance.Form .c_str(), instance.Name.c_str(), instance.Radius); + instance.Plant = true; + } + else + { + instance.Plant = false; + } + } } - */ - return false; + return true; +} + +bool unbuildFlora() +{ + CPath::addSearchPath(s_DfnDir, true, false); + CPath::addSearchPath(s_LeveldesignDir, true, false); + + return loadLeveldesign() + && loadInstances(); } bool unbuildFlora(NLMISC::CCmdArgs &args) From 57fbaf1febd5e3c4d958b2ba8426d670ef62f969 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Wed, 25 Nov 2020 08:55:14 +0800 Subject: [PATCH 04/15] Erase things from reference that aren't plants, ryzom/ryzomcore#621 --- .../ligo/unbuild_flora/unbuild_flora.cpp | 90 +++++++++++++++++-- 1 file changed, 84 insertions(+), 6 deletions(-) diff --git a/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp b/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp index 5aa411fc2..1b718ca94 100644 --- a/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp +++ b/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp @@ -47,7 +47,7 @@ //#include #include -//#include +#include #include using namespace std; @@ -90,6 +90,7 @@ struct CPoint 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) */ @@ -165,7 +166,7 @@ struct CPlant }; std::map s_ShapeToForm; -std::set s_Instances; +std::list s_Instances; bool loadLeveldesign() { @@ -235,9 +236,9 @@ bool loadInstances() instance.Pos = info.Pos; instance.Angle = info.Rot.getAngle(); instance.Scale = info.Scale.z; - string shape = toLowerAscii(info.Name); - printf("%s\n", shape.c_str()); - std::map::iterator formIt = s_ShapeToForm.find(shape); + instance.Shape = toLowerAscii(info.Name); + printf("%s\n", instance.Shape.c_str()); + std::map::iterator formIt = s_ShapeToForm.find(instance.Shape); if (formIt != s_ShapeToForm.end()) { instance.Form = formIt->second.Form; @@ -250,6 +251,81 @@ bool loadInstances() { instance.Plant = false; } + s_Instances.push_back(instance); + } + } + + return true; +} + +bool eraseReference() +{ + std::vector igs; + CPath::getPathContent(s_ReferenceDir, true, false, true, igs); + + for (std::vector::iterator it(igs.begin()), end(igs.end()); it != end; ++it) + { + if (CFile::getExtension(*it) != nlstr("ig")) + continue; + printf("%s\n", (*it).c_str()); + 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", shape.c_str()); + bool erased = false; + for (std::list::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::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", instance.Shape.c_str()); + std::list::iterator nextIt = it; + ++nextIt; + s_Instances.erase(it); + it = nextIt; + } + else + { + ++it; } } @@ -262,7 +338,9 @@ bool unbuildFlora() CPath::addSearchPath(s_LeveldesignDir, true, false); return loadLeveldesign() - && loadInstances(); + && loadInstances() + && eraseReference() + && eraseNonPlants(); } bool unbuildFlora(NLMISC::CCmdArgs &args) From b3bed095f803d479fb65fcfcb77ea030b685790f Mon Sep 17 00:00:00 2001 From: kaetemi Date: Wed, 25 Nov 2020 09:17:54 +0800 Subject: [PATCH 05/15] Write XML file, ryzom/ryzomcore#621 --- .../ligo/unbuild_flora/unbuild_flora.cpp | 91 ++++++++++++++----- 1 file changed, 70 insertions(+), 21 deletions(-) diff --git a/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp b/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp index 1b718ca94..1537c09ce 100644 --- a/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp +++ b/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp @@ -26,26 +26,18 @@ #include #include -//#include #include #include -//#include #include #include #include #include -//#include -//#include -//#include -//#include -//#include -//#include #include -//#include - +#include +#include #include #include #include @@ -178,7 +170,7 @@ bool loadLeveldesign() for (std::vector::iterator it(plants.begin()), end(plants.end()); it != end; ++it) { - printf("%s\n", (*it).c_str()); + printf("%s\n", nlUtf8ToMbcs(*it)); CSmartPtr form = formLoader->loadForm(*it); if (!form) continue; @@ -193,11 +185,11 @@ bool loadLeveldesign() } if (plant.Shape.empty()) continue; - plant.Shape.c_str(); - (void)toLowerAscii(&plant.Shape[0]); + (void)plant.Shape.c_str(); + toLowerAscii(&plant.Shape[0]); if (!form->getRootNode().getValueByName(plant.Radius, "3D.Bounding Radius")) continue; - printf(" = '%s', %f\n", plant.Shape.c_str(), plant.Radius); + printf(" = '%s', %f\n", nlUtf8ToMbcs(plant.Shape), plant.Radius); s_ShapeToForm[plant.Shape] = plant; } @@ -213,7 +205,7 @@ bool loadInstances() { if (CFile::getExtension(*it) != nlstr("ig")) continue; - printf("%s\n", (*it).c_str()); + printf("%s\n", nlUtf8ToMbcs(*it)); CInstanceGroup ig; CIFile inputStream; if (!inputStream.open(*it)) @@ -237,14 +229,14 @@ bool loadInstances() instance.Angle = info.Rot.getAngle(); instance.Scale = info.Scale.z; instance.Shape = toLowerAscii(info.Name); - printf("%s\n", instance.Shape.c_str()); + printf("%s\n", nlUtf8ToMbcs(instance.Shape)); std::map::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, instance.Form .c_str(), instance.Name.c_str(), instance.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 @@ -267,7 +259,7 @@ bool eraseReference() { if (CFile::getExtension(*it) != nlstr("ig")) continue; - printf("%s\n", (*it).c_str()); + printf("%s\n", nlUtf8ToMbcs(*it)); CInstanceGroup ig; CIFile inputStream; if (!inputStream.open(*it)) @@ -287,7 +279,7 @@ bool eraseReference() { CInstanceGroup::CInstance &info = ig._InstancesInfos[i]; string shape = toLowerAscii(info.Name); - printf("%s\n", shape.c_str()); + printf("%s\n", nlUtf8ToMbcs(shape)); bool erased = false; for (std::list::iterator it(s_Instances.begin()), end(s_Instances.end()); it != end; ++it) { @@ -317,7 +309,7 @@ bool eraseNonPlants() const CPoint &instance = *it; if (!instance.Plant) { - printf("Erase '%s' because it's not a plant!\n", instance.Shape.c_str()); + printf("Erase '%s' because it's not a plant!\n", nlUtf8ToMbcs(instance.Shape)); std::list::iterator nextIt = it; ++nextIt; s_Instances.erase(it); @@ -332,6 +324,62 @@ bool eraseNonPlants() return true; } +bool writeFlora() +{ + ofstream fo; + fo.open(utf8ToWide(s_PrimitiveFile)); + fo << "\n"; + fo << "\n"; + fo << " \n"; + fo << " \n"; + fo << " \n"; + fo << " \n"; + fo << " class\n"; + fo << " flora\n"; + fo << " \n"; + fo << " \n"; + fo << " name\n"; + fo << " " << CFile::getFilenameWithoutExtension(s_PrimitiveFile) << "_flora\n"; + fo << " \n"; + for (std::list::iterator it(s_Instances.begin()), end(s_Instances.end()); it != end; ++it) + { + const CPoint &instance = *it; + fo << " \n"; + fo << " \n"; + fo << " \n"; + fo << " \n"; + fo << " class\n"; + fo << " prim\n"; + fo << " \n"; + fo << " \n"; + fo << " form\n"; + fo << " " << CFile::getFilenameWithoutExtension(instance.Form) << "\n"; + fo << " \n"; + fo << " \n"; + fo << " layer\n"; + fo << " 0\n"; + fo << " \n"; + fo << " \n"; + fo << " name\n"; + fo << " " << instance.Name << "\n"; + fo << " \n"; + fo << " \n"; + fo << " radius\n"; + fo << " " << instance.Radius << "\n"; + fo << " \n"; + fo << " \n"; + fo << " scale\n"; + fo << " " << instance.Scale << "\n"; + fo << " \n"; + fo << " \n"; + } + fo << " \n"; + fo << " \n"; + fo << "\n"; + printf("Generated:\n%s\n", nlUtf8ToMbcs(s_PrimitiveFile)); + return true; +} + bool unbuildFlora() { CPath::addSearchPath(s_DfnDir, true, false); @@ -340,7 +388,8 @@ bool unbuildFlora() return loadLeveldesign() && loadInstances() && eraseReference() - && eraseNonPlants(); + && eraseNonPlants() + && writeFlora(); } bool unbuildFlora(NLMISC::CCmdArgs &args) From 813b4d72d16e5a33afbc9d2d52d3bc878cfd7423 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Wed, 25 Nov 2020 09:31:26 +0800 Subject: [PATCH 06/15] Notes --- nel/tools/ligo/unbuild_flora/unbuild_flora.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp b/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp index 1537c09ce..98aa70954 100644 --- a/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp +++ b/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp @@ -72,6 +72,10 @@ std::string s_PrimitiveFile; /* R:\graphics\primitive\r2_desert\r2_desert.primit 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" */ From aa7d667b10403d297948cc3d49b97327c3d78957 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Wed, 25 Nov 2020 09:31:52 +0800 Subject: [PATCH 07/15] Show angle --- nel/tools/3d/ig_info/ig_info.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nel/tools/3d/ig_info/ig_info.cpp b/nel/tools/3d/ig_info/ig_info.cpp index f1fa9b5e2..326d51ac2 100644 --- a/nel/tools/3d/ig_info/ig_info.cpp +++ b/nel/tools/3d/ig_info/ig_info.cpp @@ -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"); From 257f6a6e237a323b117e7a7c75f5e6ad3422fcb0 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Wed, 25 Nov 2020 09:43:52 +0800 Subject: [PATCH 08/15] Build fix --- nel/tools/ligo/unbuild_flora/unbuild_flora.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp b/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp index 98aa70954..3c6612a10 100644 --- a/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp +++ b/nel/tools/ligo/unbuild_flora/unbuild_flora.cpp @@ -331,7 +331,11 @@ bool eraseNonPlants() bool writeFlora() { ofstream fo; +#ifdef NL_OS_WINDOWS fo.open(utf8ToWide(s_PrimitiveFile)); +#else + fo.open(s_PrimitiveFile); +#endif fo << "\n"; fo << "\n"; fo << " \n"; From 3df1fd3857a983be4d19e9c4ec656064fdd1f881 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Thu, 26 Nov 2020 00:30:49 +0800 Subject: [PATCH 09/15] Notes --- nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm_rt.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm_rt.cpp b/nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm_rt.cpp index 53aff48ba..c2eb6a4af 100644 --- a/nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm_rt.cpp +++ b/nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm_rt.cpp @@ -366,7 +366,7 @@ void CRTWorld::addNode (INode *pNode, vector< CMesh::CMeshBuild* > &Meshes, vec { 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; @@ -382,7 +382,7 @@ void CRTWorld::addNode (INode *pNode, vector< CMesh::CMeshBuild* > &Meshes, vec { CMesh::CMeshBuild *pMB; CMeshBase::CMeshBaseBuild *pMBB; - pMB = exportNel.createMeshBuild ( *pNode, tvTime, pMBB); + pMB = exportNel.createMeshBuild ( *pNode, tvTime, pMBB); // FIXME: This is slow! if( pMBB->bCastShadows ) { Meshes.push_back( pMB ); From 147cb75a80e089a7fefb02b396720c46e132979e Mon Sep 17 00:00:00 2001 From: kaetemi Date: Thu, 26 Nov 2020 01:18:54 +0800 Subject: [PATCH 10/15] Temporary cache implementation for lightmapping during export --- .../3d/plugin_max/nel_mesh_lib/calc_lm_rt.cpp | 98 +++++++++++++++---- .../3d/plugin_max/nel_mesh_lib/calc_lm_rt.h | 6 ++ 2 files changed, 85 insertions(+), 19 deletions(-) diff --git a/nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm_rt.cpp b/nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm_rt.cpp index c2eb6a4af..7fc5c4e85 100644 --- a/nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm_rt.cpp +++ b/nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm_rt.cpp @@ -32,6 +32,11 @@ using namespace NLMISC; // CRTWorld // *********************************************************************************************** +std::map> CRTWorld::s_WorldCache; +std::map 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 &AllLights, const set &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::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)) // FIXME: This is always true with sunlight! + 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); // FIXME: This is slow! - if( pMBB->bCastShadows ) + std::map>::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 &AllLights, const set &excludeNode, const set &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>::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 &AllLights, const set &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>::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(); diff --git a/nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm_rt.h b/nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm_rt.h index 11bb825d0..a017ce03c 100644 --- a/nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm_rt.h +++ b/nel/tools/3d/plugin_max/nel_mesh_lib/calc_lm_rt.h @@ -131,6 +131,12 @@ class CRTWorld //vector cgAccel; // One cube grid by light point or spot //vector dirAccel; // One grid by light (directionnal only) NLMISC::CVector GlobalTrans; + + static std::map> s_WorldCache; + static std::map 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); From abf2715fa31c88e6d1b35bf1391ad9cd02d3eae3 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Fri, 27 Nov 2020 11:01:17 +0800 Subject: [PATCH 11/15] Create more consistent R2 maps --- .../processes/cartographer/0_setup.py | 8 ++++++-- .../r2_islands_textures/screenshot_islands.cpp | 18 ++++++++++++------ 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/nel/tools/build_gamedata/processes/cartographer/0_setup.py b/nel/tools/build_gamedata/processes/cartographer/0_setup.py index 6f8b9a754..0263edbda 100644 --- a/nel/tools/build_gamedata/processes/cartographer/0_setup.py +++ b/nel/tools/build_gamedata/processes/cartographer/0_setup.py @@ -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") diff --git a/ryzom/tools/client/r2_islands_textures/screenshot_islands.cpp b/ryzom/tools/client/r2_islands_textures/screenshot_islands.cpp index f76b1baf3..13c343881 100644 --- a/ryzom/tools/client/r2_islands_textures/screenshot_islands.cpp +++ b/ryzom/tools/client/r2_islands_textures/screenshot_islands.cpp @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -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 zonesAdded; vector 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; From 6bed86797bf467bc261e4b432940a6881bd9db16 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 7 Dec 2020 15:05:02 +0200 Subject: [PATCH 12/15] Add --url, --app options for client patcher --- CMakeLists.txt | 2 ++ config.h.cmake | 1 + ryzom/tools/client/client_patcher/main.cpp | 26 ++++++++++++++++++++-- 3 files changed, 27 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 07fe11c8e..6bbf6235e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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") diff --git a/config.h.cmake b/config.h.cmake index fa4749cb2..fa6c456b9 100644 --- a/config.h.cmake +++ b/config.h.cmake @@ -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}" diff --git a/ryzom/tools/client/client_patcher/main.cpp b/ryzom/tools/client/client_patcher/main.cpp index 26db547ac..6ab6d860b 100644 --- a/ryzom/tools/client/client_patcher/main.cpp +++ b/ryzom/tools/client/client_patcher/main.cpp @@ -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,6 +201,8 @@ int main(int argc, char *argv[]) Args.setVersion(getDisplayVersion()); Args.setDescription("Ryzom client"); + 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; @@ -240,16 +243,35 @@ 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()); // initialize patch manager and set the ryzom full path, before it's used CPatchManager *pPM = CPatchManager::getInstance(); // use PatchUrl vector patchURLs; - pPM->init(patchURLs, PatchUrl, ""); + pPM->init(patchURLs, ClientCfg.ConfigFile.getVar("PatchUrl").asString(), ""); pPM->startCheckThread(true /* include background patchs */); string state; From 53437989d4829639fcc8e096bf5d30bd6b99e11c Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 31 Dec 2020 15:55:41 +0200 Subject: [PATCH 13/15] Add --list-verbose, --extract options to bnp_make --- nel/tools/misc/bnp_make/main.cpp | 56 ++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/nel/tools/misc/bnp_make/main.cpp b/nel/tools/misc/bnp_make/main.cpp index 2edf0a7ba..0bda1770e 100644 --- a/nel/tools/misc/bnp_make/main.cpp +++ b/nel/tools/misc/bnp_make/main.cpp @@ -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 + 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; } From 779f87d6e719a771a5c7ad43224e54b4e50e880a Mon Sep 17 00:00:00 2001 From: Nimetu Date: Tue, 29 Dec 2020 12:19:32 +0200 Subject: [PATCH 14/15] Change CFile::setRWAccess to only set rw-rw-r-- (+x for directories) on linux/macOS. --- nel/include/nel/misc/path.h | 7 ++++ nel/src/misc/path.cpp | 44 ++++++++++++++++++++-- ryzom/client/src/login_patch.cpp | 1 + ryzom/tools/client/client_patcher/main.cpp | 22 ++++++----- 4 files changed, 62 insertions(+), 12 deletions(-) diff --git a/nel/include/nel/misc/path.h b/nel/include/nel/misc/path.h index 74e24d715..6f3bb8fe1 100644 --- a/nel/include/nel/misc/path.h +++ b/nel/include/nel/misc/path.h @@ -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. */ diff --git a/nel/src/misc/path.cpp b/nel/src/misc/path.cpp index 2c55ac09f..ffa27d193 100644 --- a/nel/src/misc/path.cpp +++ b/nel/src/misc/path.cpp @@ -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); diff --git a/ryzom/client/src/login_patch.cpp b/ryzom/client/src/login_patch.cpp index d9d7e2e99..6fc6da999 100644 --- a/ryzom/client/src/login_patch.cpp +++ b/ryzom/client/src/login_patch.cpp @@ -1035,6 +1035,7 @@ void CPatchManager::executeBatchFile() // make script executable CFile::setRWAccess(batchFilename); + CFile::setExecutable(batchFilename); // append login, password and shard if (!LoginLogin.empty()) diff --git a/ryzom/tools/client/client_patcher/main.cpp b/ryzom/tools/client/client_patcher/main.cpp index 6ab6d860b..9855a6b65 100644 --- a/ryzom/tools/client/client_patcher/main.cpp +++ b/ryzom/tools/client/client_patcher/main.cpp @@ -351,6 +351,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"); @@ -381,17 +382,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; } From d9d9c6e1e6b6aad5d7f06029a08c04a744a9a942 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Sat, 2 Jan 2021 16:45:39 +0200 Subject: [PATCH 15/15] Fix css style order when using external css files --- nel/include/nel/gui/group_html.h | 7 ++- nel/include/nel/gui/html_parser.h | 17 +++++-- nel/src/gui/group_html.cpp | 83 ++++++++++++++++++++----------- nel/src/gui/html_parser.cpp | 16 +++--- 4 files changed, 80 insertions(+), 43 deletions(-) diff --git a/nel/include/nel/gui/group_html.h b/nel/include/nel/gui/group_html.h index a96f0180a..172c8b434 100644 --- a/nel/include/nel/gui/group_html.h +++ b/nel/include/nel/gui/group_html.h @@ -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 _StylesheetQueue; + std::vector _StylesheetQueue; + //