Пример #1
0
bool XmlWorldReader::Read(const std::string &file) {
	// ワールドを初期化
	try {
		initialize();
		if (initFlag) {
			initializeWorld();
		}
	} catch (...) {
		return false;
	}

	// TODO: ファイルの有無を確認

	// XMLファイルをパース
	const XMLCh gLS[] = {chLatin_L, chLatin_S, chNull};
	DOMImplementationLS *impl = DOMImplementationRegistry::getDOMImplementation(gLS);
	DOMLSParser *parser = impl->createLSParser(
		DOMImplementationLS::MODE_SYNCHRONOUS, NULL
	);
	DOMDocument *doc = parser->parseURI(file.c_str());
	if (doc == nullptr) {
		return false;
	}

	// rootノードを取得
	DOMElement *worldElement = doc->getDocumentElement();
	if (worldElement == nullptr) {
		parser->release();
		return false;
	}
	{
		YPT::XmlString temp("world");
		bool res = XMLString::equals(worldElement->getNodeName(), temp);
		if (!res) {
			parser->release();
			return false;
		}
	}

	// ロード用クラス作成
	YPT::XmlWorldPartReader partReader(doc);

	// XPathコンテキスト作成
	DOMXPathNSResolver *resolver = doc->createNSResolver(worldElement);
	if (resolver == nullptr) {
		parser->release();
		return false;
	}

	YPT::XmlString str, str2;
	DOMXPathResult *result;

	// --------------------------------------------------
	// ワールド全体の設定
	// --------------------------------------------------

	// ワールド名
	str = worldElement->getAttribute(YPT::XmlString("name"));
	if (str != "") {
		name = str;
	}

	// 重力ベクトル
	result = doc->evaluate(
		YPT::XmlString("./gravity"), worldElement, resolver,
		DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
		NULL
	);
	if (result != nullptr) {
		if (result->getSnapshotLength() >= 1) {
			str = result->getNodeValue()->getTextContent();
			b2Vec2 temp;
			if (!YPT::ConvertStrToVec2(str.ToChar(), &temp)) {
				world.SetGravity(temp);
			}
		}
		result->release();
	}

	// --------------------------------------------------
	// shapes
	// --------------------------------------------------

	result = doc->evaluate(
		YPT::XmlString("./shape"), worldElement, resolver,
		DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
		NULL
	);
	if (result != nullptr) {
		const XMLSize_t len = result->getSnapshotLength();
		for (XMLSize_t i = 0; i < len; ++i) {
			result->snapshotItem(i);
			DOMNode *node = result->getNodeValue();
			if (node == nullptr) {
				continue;
			}
			DOMNamedNodeMap *nodeMap = node->getAttributes();
			if (nodeMap == nullptr) {
				continue;
			}
			DOMNode *typeNode = nodeMap->getNamedItem(YPT::XmlString("type"));
			if (typeNode == nullptr) {
				continue;
			}
			str = typeNode->getNodeValue();
			b2Shape::Type type;
			int index;
			if (str == "circle") {
				type = b2Shape::e_circle;
				b2CircleShape temp;
				if (partReader.ReadCircleShape(node, &temp)) {
					circleShapes.push_back(temp);
					index = circleShapes.size()-1;
				} else {
					// 読み込み失敗
					continue;
				}
			} else if (str == "edge") {
				type = b2Shape::e_edge;
				b2EdgeShape temp;
				if (partReader.ReadEdgeShape(node, &temp)) {
					edgeShapes.push_back(temp);
					index = edgeShapes.size()-1;
				} else {
					// 読み込み失敗
					continue;
				}
			} else if (str == "polygon") {
				type = b2Shape::e_polygon;
				b2PolygonShape temp;
				if (partReader.ReadPolygonShape(node, &temp)) {
					polygonShapes.push_back(temp);
					index = polygonShapes.size()-1;
				} else {
					// 読み込み失敗
					continue;
				}
			} else if (str == "chain") {
				type = b2Shape::e_chain;
				b2ChainShape temp;
				if (partReader.ReadChainShape(node, &temp)) {
					chainShapes.push_back(temp);
					index = chainShapes.size()-1;
				} else {
					// 読み込み失敗
					continue;
				}
			} else {
				// 未対応
				continue;
			}

			// nameプロパティがあれば保存
			DOMNode *name = nodeMap->getNamedItem(YPT::XmlString("name"));
			if (name != nullptr) {
				str = name->getNodeValue();
				shapes.insert(ShapesMap::value_type(
					std::string(str),
					std::make_pair(type, index)
				));
			}
		}
		result->release();
	}

	// --------------------------------------------------
	// fixtures
	// --------------------------------------------------

	result = doc->evaluate(
		YPT::XmlString("./fixture"), worldElement, resolver,
		DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
		NULL
	);
	if (result != nullptr) {
		const XMLSize_t len = result->getSnapshotLength();
		for (XMLSize_t i = 0; i < len; ++i) {
			result->snapshotItem(i);
			DOMNode *node = result->getNodeValue();
			if (node == nullptr) {
				continue;
			}
			DOMXPathResult *result2 = doc->evaluate(
				YPT::XmlString("./shape"), node, resolver,
				DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
				NULL
			);
			if (result2 == nullptr) {
				continue;
			}
			DOMNode *shapeNode = result2->getNodeValue();
			if (shapeNode == nullptr) {
				continue;
			}
			str = shapeNode->getTextContent();
			result2->release();
			ShapesMap::iterator found = shapes.find(std::string(str));
			if (found == shapes.end()) {
				continue;
			}

			// fixture読み込み
			b2FixtureDef fixtureDef;
			b2Shape *shape = NULL;
			int index = found->second.second;
			switch (found->second.first) {
			case b2Shape::e_circle:
				shape = &circleShapes[index];
				break;
			case b2Shape::e_edge:
				shape = &edgeShapes[index];
				break;
			case b2Shape::e_polygon:
				shape = &polygonShapes[index];
				break;
			case b2Shape::e_chain:
				shape = &chainShapes[index];
				break;
			default:
				// 未対応
				break;
			}
			if (shape == NULL) {
				continue;
			}
			if (partReader.ReadFixture(node, shape, &fixtureDef)) {
				// 読み込み成功
				// nameプロパティがあれば保存する
				DOMNamedNodeMap *nodeMap = node->getAttributes();
				if (nodeMap == nullptr) {
					continue;
				}
				DOMNode *nameNode = nodeMap->getNamedItem(YPT::XmlString("name"));
				if (nameNode == nullptr) {
					continue;
				}
				str = nameNode->getNodeValue();
				fixtures.insert(FixturesMap::value_type(
					std::string(str), fixtureDef
				));
			}
		}
		result->release();
	}

	// --------------------------------------------------
	// bodies
	// --------------------------------------------------

	result = doc->evaluate(
		YPT::XmlString("./body"), worldElement, resolver,
		DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
		NULL
	);
	if (result != nullptr) {
		const XMLSize_t len = result->getSnapshotLength();
		for (XMLSize_t i = 0; i < len; ++i) {
			result->snapshotItem(i);
			DOMNode *node = result->getNodeValue();
			if (node == nullptr) {
				continue;
			}
			DOMXPathResult *result2 = doc->evaluate(
				YPT::XmlString("./fixtures/fixture"), node, resolver,
				DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
				NULL
			);
			if (result2 == nullptr) {
				continue;
			}
			std::vector< b2FixtureDef *> fixtureDefs;
			const XMLSize_t fixturesLen = result2->getSnapshotLength();
			for (XMLSize_t j = 0; j < fixturesLen; ++j) {
				result2->snapshotItem(j);
				DOMNode *fixtureNode = result2->getNodeValue();
				if (fixtureNode == nullptr) {
					continue;
				}
				str = fixtureNode->getTextContent();
				FixturesMap::iterator found = fixtures.find(
					std::string(str)
				);
				if (found != fixtures.end()) {
					fixtureDefs.push_back(&found->second);
				}
			}
			result2->release();

			b2Body *body = partReader.ReadBody(world, node, fixtureDefs);
			if (body != nullptr) {
				// 読み込み成功
				// nameプロパティがあれば保存する
				DOMNamedNodeMap *nodeMap = node->getAttributes();
				if (nodeMap == nullptr) {
					continue;
				}
				DOMNode *nameNode = nodeMap->getNamedItem(YPT::XmlString("name"));
				if (nameNode == nullptr) {
					continue;
				}
				str = nameNode->getNodeValue();
				bodies.insert(BodiesMap::value_type(
					std::string(str), body
				));
			}
		}
		result->release();
	}

	// --------------------------------------------------
	// 読み込み完了
	// --------------------------------------------------

	resolver->release();
	parser->release();

	return true;
}
bool SignatureSetImporter::execute(PlugInArgList* pInArgList, PlugInArgList* OutArgList)
{
   VERIFY(pInArgList != NULL);
   Progress* pProgress = pInArgList->getPlugInArgValue<Progress>(Executable::ProgressArg());
   ProgressTracker progress(pProgress, "Loading spectral signature library", "spectral", "7B21EE8A-D2E1-4325-BB9F-F4E521BFD5ED");

   SignatureSet* pSignatureSet = pInArgList->getPlugInArgValue<SignatureSet>(Importer::ImportElementArg());
   VERIFY(pSignatureSet != NULL);
   DataDescriptor* pDataDescriptor = pSignatureSet->getDataDescriptor();
   VERIFY(pDataDescriptor != NULL);
   FileDescriptor* pFileDescriptor = pDataDescriptor->getFileDescriptor();
   VERIFY(pFileDescriptor != NULL);
   const string& filename = pFileDescriptor->getFilename().getFullPathAndName();

   progress.getCurrentStep()->addProperty("signature set", pSignatureSet->getName());
   progress.getCurrentStep()->addProperty("dataset location", pFileDescriptor->getDatasetLocation());

   // locate the spot in the tree for this dataset
   try
   {
      string expr;
      vector<string> parts = StringUtilities::split(pFileDescriptor->getDatasetLocation(), '/');
      for (vector<string>::iterator part = parts.begin(); part != parts.end(); ++part)
      {
         if (!part->empty())
         {
            expr += "/signature_set[metadata/@name='Name' and metadata/@value='" + *part + "']";
         }
      }
      expr += "/signature";
      loadDoc(filename);
      DOMXPathResult* pResult = mXml[filename]->query(expr, DOMXPathResult::SNAPSHOT_RESULT_TYPE);
      VERIFY(pResult != NULL);
      int nodeTotal = pResult->getSnapshotLength();
      for (int nodeNum = 0; nodeNum < nodeTotal; ++nodeNum)
      {
         if (isAborted())
         {
            progress.report("Aborted file " + pFileDescriptor->getFilename().getFullPathAndName(), 0, WARNING, true);
            progress.report("User aborted the operation.", 0, ABORT, true);
            return false;
         }
         int percent = static_cast<int>(100.0 * nodeNum / nodeTotal);
         progress.report("Importing signature library", percent, NORMAL);
         if (!pResult->snapshotItem(nodeNum) || !pResult->isNode())
         {
            continue;
         }
         const DOMElement* pElmnt = static_cast<const DOMElement*>(pResult->getNodeValue());
         string filename = A(pElmnt->getAttribute(X("filename")));
         if (filename.empty() == false)
         {
            string path = pFileDescriptor->getFilename().getPath();

            QString tempFilename = QString::fromStdString(filename);
            if (tempFilename.startsWith("./") == true)
            {
               tempFilename.replace(0, 1, QString::fromStdString(path));
               filename = tempFilename.toStdString();
            }
            else
            {
               QFileInfo fileInfo(tempFilename);
               if (fileInfo.isRelative() == true)
               {
                  filename = path + SLASH + filename;
               }
            }
         }

         // don't pass progress to importer - the individual signature imports are rapid and passing progress will
         // cause isAborted() to not function properly.
         ImporterResource importer("Auto Importer", filename, NULL);
         if (importer->getPlugIn() == NULL)
         {
            progress.report("The \"Auto Importer\" is not available and is required to import signature sets.", 0, ERRORS, true);
            return false;
         }
         if (importer->execute())
         {
            vector<DataElement*> elements = importer->getImportedElements();
            vector<Signature*> sigs(elements.size(), NULL);
            for (vector<DataElement*>::iterator element = elements.begin(); element != elements.end(); ++element)
            {
               Signature* pSig = dynamic_cast<Signature*>(*element);
               if (pSig != NULL)
               {
                  pSignatureSet->insertSignature(pSig);
                  // reparent the signature
                  Service<ModelServices>()->setElementParent(pSig, pSignatureSet);
               }
            }
         }
         else
         {
            progress.report("Unable to import signature " + filename, percent, WARNING, true);
         }
      }
   }
   catch(DOMException &exc)
   {
      progress.report(A(exc.getMessage()), 0, ERRORS, true);
      return false;
   }
   SignatureSet* pParent = dynamic_cast<SignatureSet*>(pSignatureSet->getParent());
   if (pParent != NULL && pParent->getFilename() == pSignatureSet->getFilename())
   {
      pParent->insertSignature(pSignatureSet);
   }

   progress.report("Spectral signature library loaded", 100, NORMAL);
   progress.upALevel();
   return true;
}