CC中有两个地方使用了文件保存,一个是MainWindow,另一个是ccCommandLineParser。
MainWindow的保存按钮关联的槽是doActionSaveFile()方法,实现了点云和Mesh的保存。
void MainWindow::doActionSaveFile()
{
size_t selNum = m_selectedEntities.size();
if (selNum == )
return; ccHObject clouds("clouds");
ccHObject meshes("meshes");
ccHObject images("images");
ccHObject polylines("polylines");
ccHObject other("other");
ccHObject otherSerializable("serializable");
ccHObject::Container entitiesToDispatch;
entitiesToDispatch.insert(entitiesToDispatch.begin(),m_selectedEntities.begin(),m_selectedEntities.end());
ccHObject entitiesToSave;
while (!entitiesToDispatch.empty())
{
ccHObject* child = entitiesToDispatch.back();
entitiesToDispatch.pop_back(); if (child->isA(CC_TYPES::HIERARCHY_OBJECT))
{
for (unsigned j=; j<child->getChildrenNumber(); ++j)
entitiesToDispatch.push_back(child->getChild(j));
}
else
{
//we put the entity in the container corresponding to its type
ccHObject* dest = ;
if (child->isA(CC_TYPES::POINT_CLOUD))
dest = &clouds;
else if (child->isKindOf(CC_TYPES::MESH))
dest = &meshes;
else if (child->isKindOf(CC_TYPES::IMAGE))
dest = &images;
else if (child->isKindOf(CC_TYPES::POLY_LINE))
dest = &polylines;
else if (child->isSerializable())
dest = &otherSerializable;
else
dest = &other; assert(dest); //we don't want double insertions if the user has clicked both the father and child
if (!dest->find(child->getUniqueID()))
{
dest->addChild(child,ccHObject::DP_NONE);
entitiesToSave.addChild(child,ccHObject::DP_NONE);
}
}
} bool hasCloud = (clouds.getChildrenNumber() != );
bool hasMesh = (meshes.getChildrenNumber() != );
bool hasImages = (images.getChildrenNumber() != );
bool hasPolylines = (polylines.getChildrenNumber() != );
bool hasSerializable = (otherSerializable.getChildrenNumber() != );
bool hasOther = (other.getChildrenNumber() != ); int stdSaveTypes = static_cast<int>(hasCloud)
+ static_cast<int>(hasMesh)
+ static_cast<int>(hasImages)
+ static_cast<int>(hasPolylines)
+ static_cast<int>(hasSerializable);
if (stdSaveTypes == )
{
ccConsole::Error("Can't save selected entity(ies) this way!");
return;
} //we set up the right file filters, depending on the selected
//entities type (cloud, mesh, etc.).
QStringList fileFilters;
{
const FileIOFilter::FilterContainer& filters = FileIOFilter::GetFilters();
for (size_t i=; i<filters.size(); ++i)
{
bool atLeastOneExclusive = false; //current I/O filter
const FileIOFilter::Shared filter = filters[i]; //does this filter can export one or several clouds?
bool canExportClouds = true;
if (hasCloud)
{
bool isExclusive = true;
bool multiple = false;
canExportClouds = ( filter->canSave(CC_TYPES::POINT_CLOUD,multiple,isExclusive)
&& (multiple || clouds.getChildrenNumber() == ) );
atLeastOneExclusive |= isExclusive;
} //does this filter can export one or several meshes?
bool canExportMeshes = true;
if (hasMesh)
{
bool isExclusive = true;
bool multiple = false;
canExportMeshes = ( filter->canSave(CC_TYPES::MESH,multiple,isExclusive)
&& (multiple || meshes.getChildrenNumber() == ) );
atLeastOneExclusive |= isExclusive;
} //does this filter can export one or several polylines?
bool canExportPolylines = true;
if (hasPolylines)
{
bool isExclusive = true;
bool multiple = false;
canExportPolylines = ( filter->canSave(CC_TYPES::POLY_LINE,multiple,isExclusive)
&& (multiple || polylines.getChildrenNumber() == ) );
atLeastOneExclusive |= isExclusive;
} //does this filter can export one or several images?
bool canExportImages = true;
if (hasImages)
{
bool isExclusive = true;
bool multiple = false;
canExportImages = ( filter->canSave(CC_TYPES::IMAGE,multiple,isExclusive)
&& (multiple || images.getChildrenNumber() == ) );
atLeastOneExclusive |= isExclusive;
} //does this filter can export one or several other serializable entities?
bool canExportSerializables = true;
if (hasSerializable)
{
//check if all entities have the same type
{
CC_CLASS_ENUM firstClassID = otherSerializable.getChild()->getUniqueID();
for (unsigned j=; j<otherSerializable.getChildrenNumber(); ++j)
{
if (otherSerializable.getChild(j)->getUniqueID() != firstClassID)
{
//we add a virtual second 'stdSaveType' so as to properly handle exlusivity
++stdSaveTypes;
break;
}
}
} for (unsigned j=; j<otherSerializable.getChildrenNumber(); ++j)
{
ccHObject* child = otherSerializable.getChild(j);
bool isExclusive = true;
bool multiple = false;
canExportSerializables &= ( filter->canSave(child->getUniqueID(),multiple,isExclusive)
&& (multiple || otherSerializable.getChildrenNumber() == ) );
atLeastOneExclusive |= isExclusive;
}
} bool useThisFilter = canExportClouds
&& canExportMeshes
&& canExportImages
&& canExportPolylines
&& canExportSerializables
&& (!atLeastOneExclusive || stdSaveTypes == ); if (useThisFilter)
{
QStringList ff = filter->getFileFilters(false);
for (int j=; j<ff.size(); ++j)
fileFilters.append(ff[j]);
}
}
} //persistent settings
QSettings settings;
settings.beginGroup(ccPS::SaveFile()); //default filter
QString selectedFilter = fileFilters.first();
if (hasCloud)
selectedFilter = settings.value(ccPS::SelectedOutputFilterCloud(),selectedFilter).toString();
else if (hasMesh)
selectedFilter = settings.value(ccPS::SelectedOutputFilterMesh(), selectedFilter).toString();
else if (hasImages)
selectedFilter = settings.value(ccPS::SelectedOutputFilterImage(), selectedFilter).toString();
else if (hasPolylines)
selectedFilter = settings.value(ccPS::SelectedOutputFilterPoly(), selectedFilter).toString(); //default output path (+ filename)
QString currentPath = settings.value(ccPS::CurrentPath(),QApplication::applicationDirPath()).toString();
QString fullPathName = currentPath;
if (selNum == )
{
//hierarchy objects have generally as name: 'filename.ext (fullpath)'
//so we must only take the first part! (otherwise this type of name
//with a path inside perturbs the QFileDialog a lot ;))
QString defaultFileName(m_selectedEntities.front()->getName());
if (m_selectedEntities.front()->isA(CC_TYPES::HIERARCHY_OBJECT))
{
QStringList parts = defaultFileName.split(' ',QString::SkipEmptyParts);
if (parts.size() > )
defaultFileName = parts[];
} //we remove the extension
defaultFileName = QFileInfo(defaultFileName).baseName(); if (!IsValidFileName(defaultFileName))
{
ccLog::Warning("[I/O] First entity's name would make an invalid filename! Can't use it...");
defaultFileName = "project";
} fullPathName += QString("/") + defaultFileName;
} //ask the user for the output filename
QString selectedFilename = QFileDialog::getSaveFileName(this,
"Save file",
fullPathName,
fileFilters.join(s_fileFilterSeparator),
&selectedFilter); if (selectedFilename.isEmpty())
{
//process cancelled by the user
return;
} //ignored items
if (hasOther)
{
ccConsole::Warning("[I/O] The following selected entites won't be saved:");
for (unsigned i=; i<other.getChildrenNumber(); ++i)
ccConsole::Warning(QString("\t- %1s").arg(other.getChild(i)->getName()));
} CC_FILE_ERROR result = CC_FERR_NO_ERROR;
FileIOFilter::SaveParameters parameters;
{
parameters.alwaysDisplaySaveDialog = true;
parameters.parentWidget = this;
} //specific case: BIN format
if (selectedFilter == BinFilter::GetFileFilter())
{
if (selNum == )
{
result = FileIOFilter::SaveToFile(m_selectedEntities.front(),selectedFilename,parameters,selectedFilter);
}
else
{
//we'll regroup all selected entities in a temporary group
ccHObject tempContainer;
ConvertToGroup(m_selectedEntities,tempContainer,ccHObject::DP_NONE);
if (tempContainer.getChildrenNumber())
{
result = FileIOFilter::SaveToFile(&tempContainer,selectedFilename,parameters,selectedFilter);
}
else
{
ccLog::Warning("[I/O] None of the selected entities can be saved this way...");
result = CC_FERR_NO_SAVE;
}
}
}
else if (entitiesToSave.getChildrenNumber() != )
{
//ignored items
/*if (hasSerializable)
{
if (!hasOther)
ccConsole::Warning("[I/O] The following selected entites won't be saved:"); //display this warning only if not already done
for (unsigned i=0; i<otherSerializable.getChildrenNumber(); ++i)
ccConsole::Warning(QString("\t- %1").arg(otherSerializable.getChild(i)->getName()));
}
//*/ result = FileIOFilter::SaveToFile( entitiesToSave.getChildrenNumber() > ? &entitiesToSave : entitiesToSave.getChild(),
selectedFilename,
parameters,
selectedFilter);
} //update default filters
if (hasCloud)
settings.setValue(ccPS::SelectedOutputFilterCloud(),selectedFilter);
if (hasMesh)
settings.setValue(ccPS::SelectedOutputFilterMesh(), selectedFilter);
if (hasImages)
settings.setValue(ccPS::SelectedOutputFilterImage(),selectedFilter);
if (hasPolylines)
settings.setValue(ccPS::SelectedOutputFilterPoly(), selectedFilter); //we update current file path
currentPath = QFileInfo(selectedFilename).absolutePath();
settings.setValue(ccPS::CurrentPath(),currentPath);
settings.endGroup();
}
void MainWindow::doActionSaveFile()
再看看ccCommandLineParser的Parse方法:
int ccCommandLineParser::Parse(int nargs, char** args)
{
if (!args || nargs < )
{
assert(false);
return EXIT_SUCCESS;
} //reset default behavior(s)
s_loadParameters.autoComputeNormals = false;
s_MeshExportFormat = s_CloudExportFormat = BinFilter::GetFileFilter();
s_MeshExportExt = s_CloudExportExt = BinFilter::GetDefaultExtension();
s_precision = ;
s_addTimestamp = true;
s_silentMode = false;
s_autoSaveMode = true; //load arguments
QStringList arguments;
{
for (int i=; i<nargs; ++i) //'i=1' because first argument is always program executable file!
arguments.push_back(QString(args[i]));
}
assert(!arguments.empty()); //specific command: silent mode (will prevent the console dialog from appearing!
if (IsCommand(arguments.front(),COMMAND_SILENT_MODE))
{
arguments.pop_front();
s_silentMode = true;
} QDialog consoleDlg;
if (!s_silentMode)
{
//show console
Ui_commandLineDlg commandLineDlg;
commandLineDlg.setupUi(&consoleDlg);
consoleDlg.show();
ccConsole::Init(commandLineDlg.consoleWidget, &consoleDlg);
s_loadParameters.parentWidget = &consoleDlg;
} //parse input
int result = ccCommandLineParser().parse(arguments,&consoleDlg); if (!s_silentMode)
{
if (result == EXIT_SUCCESS)
QMessageBox::information(&consoleDlg,"Processed finished","Job done");
else
QMessageBox::warning(&consoleDlg,"Processed finished","An error occurred! Check console");
} ccConsole::ReleaseInstance(); return result;
}
int ccCommandLineParser::Parse(int nargs, char** args)
该方法被main函数调用。
//主程序入口,十分重要
int main(int argc, char **argv)
{
//QT initialiation
qccApplication app(argc, argv); //Force 'english' local so as to get a consistent behavior everywhere
QLocale::setDefault(QLocale::English); #ifdef Q_OS_LINUX
// we reset the numeric locale. As suggested in documetation
// see http://qt-project.org/doc/qt-5/qcoreapplication.html#locale-settings
// Basically - from doc: - "On Unix/Linux Qt is configured to use the system locale settings by default.
// This can cause a conflict when using POSIX functions, for instance,
// when converting between data types such as floats and strings"
setlocale(LC_NUMERIC,"C");
#endif #ifdef USE_VLD
VLDEnable();
#endif //splash screen
QSplashScreen* splash = ;
QTime splashStartTime; //Command line mode?
bool commandLine = (argc > && argv[][] == '-'); //specific case: translation file selection
int lastArgumentIndex = ;
QTranslator translator;
if (commandLine && QString(argv[]).toUpper() == "-LANG")
{
QString langFilename = QString(argv[]); //Load translation file
if (translator.load(langFilename, QCoreApplication::applicationDirPath()))
{
qApp->installTranslator(&translator);
}
else
{
QMessageBox::warning(, QObject::tr("Translation"), QObject::tr("Failed to load language file '%1'").arg(langFilename));
}
commandLine = false;
lastArgumentIndex = ;
} //command line mode
if (!commandLine)
{
//OpenGL?
if (!QGLFormat::hasOpenGL())
{
QMessageBox::critical(, "Error", "This application needs OpenGL to run!");
return EXIT_FAILURE;
} //splash screen
splashStartTime.start();
QPixmap pixmap(QString::fromUtf8(":/CC/images/imLogoV2Qt.png"));
splash = new QSplashScreen(pixmap,Qt::WindowStaysOnTopHint);
splash->show();
QApplication::processEvents();
} //global structures initialization
ccTimer::Init();
FileIOFilter::InitInternalFilters(); //load all known I/O filters (plugins will come later!)
ccNormalVectors::GetUniqueInstance(); //force pre-computed normals array initialization
ccColorScalesManager::GetUniqueInstance(); //force pre-computed color tables initialization int result = ; if (commandLine)
{
//command line processing (no GUI)
result = ccCommandLineParser::Parse(argc,argv);
}
else
{
//main window init.
MainWindow* mainWindow = MainWindow::TheInstance();
if (!mainWindow)
{
QMessageBox::critical(, "Error", "Failed to initialize the main application window?!");
return EXIT_FAILURE;
}
mainWindow->show();
QApplication::processEvents(); if (argc > lastArgumentIndex)
{
if (splash)
splash->close(); //any additional argument is assumed to be a filename --> we try to load it/them
QStringList filenames;
for (int i = lastArgumentIndex; i<argc; ++i)
filenames << QString(argv[i]); mainWindow->addToDB(filenames);
} if (splash)
{
//we want the splash screen to be visible a minimum amount of time (1000 ms.)
while (splashStartTime.elapsed() < )
{
splash->raise();
QApplication::processEvents(); //to let the system breath!
} splash->close();
QApplication::processEvents(); delete splash;
splash = ;
} //let's rock!
try
{
result = app.exec();
}
catch(...)
{
QMessageBox::warning(, "CC crashed!","Hum, it seems that CC has crashed... Sorry about that :)");
}
} //release global structures
MainWindow::DestroyInstance();
FileIOFilter::UnregisterAll(); #ifdef CC_TRACK_ALIVE_SHARED_OBJECTS
//for debug purposes
unsigned alive = CCShareable::GetAliveCount();
if (alive > )
{
printf("Error: some shared objects (%u) have not been released on program end!",alive);
system("PAUSE");
}
#endif return result;
}
int main(int argc, char **argv)
两处最终都落实到FileIOFilter::SaveToFile()方法的调用。
//保存文件
CC_FILE_ERROR FileIOFilter::SaveToFile( ccHObject* entities,
const QString& filename,
SaveParameters& parameters,
QString fileFilter)
{
if (fileFilter.isEmpty())
return CC_FERR_BAD_ARGUMENT;
//获取对应的文件格式,存储器
Shared filter = GetFilter(fileFilter,false);
if (!filter)
{
ccLog::Error(QString("[Load] Internal error: no filter corresponds to filter '%1'").arg(fileFilter));
return CC_FERR_UNKNOWN_FILE;
} return SaveToFile(entities, filename, parameters, filter);
} CC_FILE_ERROR FileIOFilter::SaveToFile( ccHObject* entities,
const QString& filename,
SaveParameters& parameters,
Shared filter)
{
if (!entities || filename.isEmpty() || !filter)
return CC_FERR_BAD_ARGUMENT; //if the file name has no extension, we had a default one!
QString completeFileName(filename);
if (QFileInfo(filename).suffix().isEmpty())
completeFileName += QString(".%1").arg(filter->getDefaultExtension()); CC_FILE_ERROR result = CC_FERR_NO_ERROR;
try
{
result = filter->saveToFile(entities, completeFileName, parameters);
}
catch(...)
{
ccLog::Warning(QString("[I/O] CC has caught an unhandled exception while saving file '%1'").arg(filename));
result = CC_FERR_CONSOLE_ERROR;
} if (result == CC_FERR_NO_ERROR)
{
ccLog::Print(QString("[I/O] File '%1' saved successfully").arg(filename));
}
else
{
DisplayErrorMessage(result,"saving",filename);
} return result;
}
FileIOFilter::SaveToFile
获取需要的文件存储器。
//获取存取器
FileIOFilter::Shared FileIOFilter::GetFilter(QString fileFilter, bool onImport)
{
if (!fileFilter.isEmpty())
{
for (FilterContainer::const_iterator it=s_ioFilters.begin(); it!=s_ioFilters.end(); ++it)
{
QStringList otherFilters = (*it)->getFileFilters(onImport);
if (otherFilters.contains(fileFilter))
return *it;
}
} return Shared();
}
FileIOFilter::Shared FileIOFilter::GetFilter
这里重点研究一下obj文件的保存。
[CC]Mesh文件保存的更多相关文章
-
java 文件保存到本地
private void savePic(InputStream inputStream, String fileName) { OutputStream os = null; try { Strin ...
-
C# 文件选择对话框,Unity3d文件保存对话框
using OpenWinForm = System.Windows.Forms; 在unity3d中,使用FileDialog应该把System.Windows.Forms.dll拷贝到unity工 ...
-
怎么直接让火狐输入json数据,而不是弹出文件保存对话框?
一.问题再现: 我需要浏览器输出的是json数据,但是浏览器弹出的是一个文件保存的对话框,这样的体验有点差.所以想怎么让浏览器直接输出到浏览器的页面上面,并且格式的输出,还可以编辑. 测试数据: ht ...
-
php 下载保存文件保存到本地的两种方法
第一种: 1 <? ?> 或 <?php //下载文件保存到本地//www.jbxue.comfunction downfile($fileurl){ob_start(); $fil ...
-
使用CURL下载远程文件保存到服务器
比如微信公众平台开发,下载用户的头像到服务器上: /** * 使用CURL获取远程文件保存到服务器 *@param $image=$oJSON->headimgurl; 获取到的微信返回的头像U ...
-
(qsf文件 、 tcl文件 和 csv(txt)文件的区别) FPGA管脚分配文件保存、导入导出方法
FPGA管脚分配文件保存方法 使用别人的工程时,有时找不到他的管脚文件,但可以把他已经绑定好的管脚保存下来,输出到文件里. 方法一: 查看引脚绑定情况,quartus -> assignment ...
-
【转】warning C4819,该文件保存为 Unicode 格式以防止数据丢失,处理方法
以下的解决方案只是把错误给屏蔽掉而已,并不能真正解决这个警告.仅供参考! 当项目引用到外部源代码后,经常出现4819错误,警告信息如下: warning C4819: 该文件包含不能在当前代码页(93 ...
-
php动态网页实现页面静态化 通过在初次被访问时生成html文件保存起来,下次该PHP程序被访问时就直接找到以前被访问过的html页面
一.什么是静态页面?什么是动态页面 静态页面是网页的代码都在页面中,不需要执行asp,php,jsp,.net等程序生成客户端网页代码的网页.不能 静态页面 动态页面 区别: ...
-
重新想象 Windows 8 Store Apps (26) - 选取器: 自定义文件选取窗口, 自定义文件保存窗口
原文:重新想象 Windows 8 Store Apps (26) - 选取器: 自定义文件选取窗口, 自定义文件保存窗口 [源码下载] 重新想象 Windows 8 Store Apps (26) ...
随机推荐
-
js从服务器下载文件
通常,将文件绝对路径url作为超链接<a>的链接地址href的值,点击<a>后,浏览器将会尝试请求文件资源,如果浏览器能够辨认文件类型,则将会以预设的打开方式直接打开下载的文件 ...
-
iOS之block块
Block块. 1.声明Block int (^myBlock)(int n) = ^(int num) 类型 (^名称)(需要传的参数)= ^(参数) 2 __block 变量 在block块中修改 ...
-
SQL查看数据库所用用户表数量和使用的空间
SQL Server数据库管理员通常硬盘空间奋斗,不断努力清理“表”,撰写许多查询,发现该表使用的硬盘空间. 本文介绍了如何查询系统表的空间使用情况,帮助数据库管理员识别正在使用最多的空间,以便存档旧 ...
-
ASP.NET 打包下载文件
使用的类库为:ICSharpCode.SharpZipLib.dll 一种是打包整个文件夹,另一种是打包指定的多个文件,大同小异: using ICSharpCode.SharpZipLib.Zip; ...
-
Redis的AOF功能
引言: Redis是基于内存的数据库,同时也提供了若干持久化的方案,允许用户把内存中的数据,写入本地文件系统,以备下次重启或者当机之后继续使用.本文将描述如何基于Redis来设置AOF功能 什么是R ...
-
RabbitMQ队列
AMQP ,即Advanced Message Queuing Protocol,高级消息队列协议,是应用层协议的一个开放标准,为面向消息的中间件设计.消息中间件主要用于组件之间的解耦,消息的发送者无 ...
-
“短路求值(Short-Circuit Evaluation)
// 逻辑与和逻辑或操作符总是先计算其做操作数,只有在仅靠左操作数的值无法确定该逻辑表达式的结果时,才会求解其右操作数. function aa() { if (null) { console ...
-
Debug.Assert vs Exception Throwing(转载)
来源 Q: I've read plenty of articles (and a couple of other similar questions that were posted on Stac ...
-
numpy数学数据处理
数学和统计方法 sum 对数组中全部或某轴向的元素求和.零长度的数组的sum为0. mean 算术平均数.零长度的数组的mean为NaN. import numpy as np import nump ...
-
18年春招某编程题:有三个整数X,Y,Z,要求进行若干次操作使得X,Y,Z相等
题目描述: 给定三个整数X,Y,Z,要求进行若干次操作使得X,Y,Z相等,操作有两种: 1.从X,Y,Z中选择两个数都加1. 2.从X,Y,Z中选择一个数加2. 求最少需要多少次操作. 题目思路: 1 ...