bool XmlWorldPartReader::ReadEdgeShape(
	const DOMNode *shapeNode, b2EdgeShape *dest
) {
	DOMXPathNSResolver *resolver = doc->createNSResolver(shapeNode);
	if (resolver == nullptr) {
		return nullptr;
	}

	DOMXPathResult *result;
	YPT::XmlString str;

	b2Vec2 vec1, vec2;

	result = doc->evaluate(
		YPT::XmlString("./vertex1"), shapeNode, resolver,
		DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
		NULL
	);
	if (result == nullptr) {
		return false;
	}
	if (result->getSnapshotLength() == 0) {
		// 値が存在しない
		result->release();
		return false;
	}
	str = result->getNodeValue()->getTextContent();
	result->release();
	if (!YPT::ConvertStrToVec2(std::string(str), &vec1)) {
		// 値が正しい形式で書かれていない
		return false;
	}

	result = doc->evaluate(
		YPT::XmlString("./vertex2"), shapeNode, resolver,
		DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
		NULL
	);
	if (result == nullptr) {
		return false;
	}
	if (result->getSnapshotLength() == 0) {
		// 値が存在しない
		result->release();
		return false;
	}
	str = result->getNodeValue()->getTextContent();
	result->release();
	if (!YPT::ConvertStrToVec2(std::string(str), &vec2)) {
		// 値が正しい形式で書かれていない
		return false;
	}

	dest->m_vertex1 = vec1;
	dest->m_vertex2 = vec2;

	return true;
}
bool XmlWorldPartReader::ReadCircleShape(
	const DOMNode *shapeNode, b2CircleShape *dest
) {
	DOMXPathNSResolver *resolver = doc->createNSResolver(shapeNode);
	if (resolver == nullptr) {
		return nullptr;
	}

	DOMXPathResult *result;
	YPT::XmlString str;

	b2Vec2 center(0.0f, 0.0f);
	float32 radius;

	result = doc->evaluate(
		YPT::XmlString("./center"), shapeNode, resolver,
		DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
		NULL
	);
	if (result != nullptr) {
		if (result->getSnapshotLength() >= 1) {
			str = result->getNodeValue()->getTextContent();
			YPT::ConvertStrToVec2(std::string(str), &center);
		}
		result->release();
	}

	result = doc->evaluate(
		YPT::XmlString("./radius"), shapeNode, resolver,
		DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
		NULL
	);
	if (result == nullptr) {
		return false;
	}
	if (result->getSnapshotLength() == 0) {
		// 値が存在しない
		result->release();
		return false;
	}
	str = result->getNodeValue()->getTextContent();
	if (!YPT::ConvertStrToFloat(std::string(str), &radius)) {
		// 値が正しい形式で書かれていない
		return false;
	}
	result->release();

	dest->m_p = center;
	dest->m_radius = radius;

	return true;
}
Ejemplo n.º 3
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 XmlWorldPartReader::ReadChainShape(
	const DOMNode *shapeNode, b2ChainShape *dest
) {
	DOMXPathNSResolver *resolver = doc->createNSResolver(shapeNode);
	if (resolver == nullptr) {
		return nullptr;
	}

	DOMXPathResult *result;
	YPT::XmlString str;

	int vertexCount;
	b2Vec2 vertices[b2_maxPolygonVertices];

	result = doc->evaluate(
		YPT::XmlString("./vertexCount"), shapeNode, resolver,
		DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
		NULL
	);
	if (result == nullptr) {
		return false;
	}
	if (result->getSnapshotLength() == 0) {
		// 値が存在しない
		result->release();
		return false;
	}
	str = result->getNodeValue()->getTextContent();
	result->release();
	if (!YPT::ConvertStrToInt(std::string(str), &vertexCount)
		|| vertexCount <= 0 || vertexCount > b2_maxPolygonVertices
	) {
		// 値が正しい形式で書かれていない
		return false;
	}

	for (int i = 0; i < vertexCount; ++i) {
		std::string iStr = YPT::ConvertIntToStr(i+1);
		result = doc->evaluate(
			YPT::XmlString((
				"./vertices/vertex" + iStr + "|./vertices/v" + iStr
			).c_str()), shapeNode, resolver,
			DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
			NULL
		);
		if (result == nullptr) {
			return false;
		}
		const XMLSize_t len = result->getSnapshotLength();
		if (len == 0) {
			// 値が存在しない
			result->release();
			return false;
		}
		str = result->getNodeValue()->getTextContent();
		result->release();
		if (!YPT::ConvertStrToVec2(std::string(str), &vertices[i])) {
			 // 値が正しい形式で書かれていない
			 return false;
		}
	}
	dest->CreateChain(vertices, vertexCount);

	return true;
}
b2Body *XmlWorldPartReader::ReadBody(
	b2World &world, const DOMNode *bodyNode,
	const std::vector< b2FixtureDef *> &fixtureDefs
) {
	DOMXPathNSResolver *resolver = doc->createNSResolver(bodyNode);
	if (resolver == nullptr) {
		return nullptr;
	}

	b2BodyDef bodyDef;
	bodyDef.position.SetZero();
	bodyDef.angle = 0.0f;
	bodyDef.fixedRotation = false;
	bodyDef.type = b2_dynamicBody;
	bodyDef.gravityScale = 1.0f;

	DOMXPathResult *result;
	YPT::XmlString str;

	// position
	result = doc->evaluate(
		YPT::XmlString("./position"), bodyNode, resolver,
		DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
		NULL
	);
	if (result != nullptr) {
		if (result->getSnapshotLength() >= 1) {
			str = result->getNodeValue()->getTextContent();
			YPT::ConvertStrToVec2(std::string(str), &bodyDef.position);
		}
		result->release();
	}

	// angle
	result = doc->evaluate(
		YPT::XmlString("./angle"), bodyNode, resolver,
		DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
		NULL
	);
	if (result != nullptr) {
		if (result->getSnapshotLength() >= 1) {
			str = result->getNodeValue()->getTextContent();
			float temp;
			if (YPT::ConvertStrToFloat(std::string(str), &temp)) {
				// 度からラジアンへ変換
				bodyDef.angle = temp * YPT::PI / 180;
			}
		}
		result->release();
	}

	// fixedRotation
	result = doc->evaluate(
		YPT::XmlString("./fixedRotation"), bodyNode, resolver,
		DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
		NULL
	);
	if (result != nullptr) {
		if (result->getSnapshotLength() >= 1) {
			str = result->getNodeValue()->getTextContent();
			YPT::ConvertStrToBool(std::string(str), &bodyDef.fixedRotation);
		}
		result->release();
	}

	// type
	result = doc->evaluate(
		YPT::XmlString("./type"), bodyNode, resolver,
		DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
		NULL
	);
	if (result != nullptr) {
		if (result->getSnapshotLength() >= 1) {
			str = result->getNodeValue()->getTextContent();
			if (str == "dynamic") {
				bodyDef.type = b2_dynamicBody;
			} else if (str == "static") {
				bodyDef.type = b2_staticBody;
			} else if (str == "kinematic") {
				bodyDef.type = b2_kinematicBody;
			} else {
				// 未対応
			}
		}
		result->release();
	}

	// gravityScale
	result = doc->evaluate(
		YPT::XmlString("./gravityScale"), bodyNode, resolver,
		DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
		NULL
	);
	if (result != nullptr) {
		if (result->getSnapshotLength() >= 1) {
			str = result->getNodeValue()->getTextContent();
			YPT::ConvertStrToFloat(std::string(str), &bodyDef.gravityScale);
		}
		result->release();
	}

	b2Body *body = world.CreateBody(&bodyDef);
	if (body == NULL) {
		return NULL;
	}

	for (std::vector< b2FixtureDef *>::const_iterator it
		= fixtureDefs.begin(); it != fixtureDefs.end(); ++it)
	{
		if (*it != NULL)
			body->CreateFixture(*it);
	}

	return body;
}
bool XmlWorldPartReader::ReadFixture(const DOMNode *fixtureNode,
	b2Shape *shape, b2FixtureDef *dest)
{
	DOMXPathNSResolver *resolver = doc->createNSResolver(fixtureNode);
	if (resolver == nullptr) {
		return nullptr;
	}

	DOMXPathResult *result;
	YPT::XmlString str;

	b2FixtureDef fixtureDef;
	fixtureDef.friction = 0.5f;
	fixtureDef.restitution = 0.5f;
	fixtureDef.density = 1.0f;

	// shape
	fixtureDef.shape = shape;

	// friction
	result = doc->evaluate(
		YPT::XmlString("./friction"), fixtureNode, resolver,
		DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
		NULL
	);
	if (result != nullptr) {
		if (result->getSnapshotLength() >= 1) {
			str = result->getNodeValue()->getTextContent();
			YPT::ConvertStrToFloat(std::string(str), &fixtureDef.friction);
		}
		result->release();
	}

	// restitution
	result = doc->evaluate(
		YPT::XmlString("./restitution"), fixtureNode, resolver,
		DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
		NULL
	);
	if (result != nullptr) {
		if (result->getSnapshotLength() >= 1) {
			str = result->getNodeValue()->getTextContent();
			YPT::ConvertStrToFloat(std::string(str), &fixtureDef.restitution);
		}
		result->release();
	}

	// density
	result = doc->evaluate(
		YPT::XmlString("./density"), fixtureNode, resolver,
		DOMXPathResult::ORDERED_NODE_SNAPSHOT_TYPE,
		NULL
	);
	if (result != nullptr) {
		if (result->getSnapshotLength() >= 1) {
			str = result->getNodeValue()->getTextContent();
			YPT::ConvertStrToFloat(std::string(str), &fixtureDef.density);
		}
		result->release();
	}

	*dest = fixtureDef;

	return true;
}