bool Animatable::SaveXML(XMLElement& dest) const { if (!Serializable::SaveXML(dest)) return false; // Object animation without name if (objectAnimation_ && objectAnimation_->GetName().Empty()) { XMLElement elem = dest.CreateChild("objectanimation"); if (!objectAnimation_->SaveXML(elem)) return false; } for (HashMap<String, SharedPtr<AttributeAnimationInfo> >::ConstIterator i = attributeAnimationInfos_.Begin(); i != attributeAnimationInfos_.End(); ++i) { ValueAnimation* attributeAnimation = i->second_->GetAnimation(); if (attributeAnimation->GetOwner()) continue; const AttributeInfo& attr = i->second_->GetAttributeInfo(); XMLElement elem = dest.CreateChild("attributeanimation"); elem.SetAttribute("name", attr.name_); if (!attributeAnimation->SaveXML(elem)) return false; elem.SetAttribute("wrapmode", wrapModeNames[i->second_->GetWrapMode()]); elem.SetFloat("speed", i->second_->GetSpeed()); } return true; }
bool Node::SaveXML(XMLElement& dest) { // Write node ID if (!dest.SetInt("id", id_)) return false; // Write attributes if (!Serializable::SaveXML(dest)) return false; // Write components for (unsigned i = 0; i < components_.Size(); ++i) { Component* component = components_[i]; XMLElement compElem = dest.CreateChild("component"); if (!component->SaveXML(compElem)) return false; } // Write child nodes for (unsigned i = 0; i < children_.Size(); ++i) { Node* node = children_[i]; XMLElement childElem = dest.CreateChild("node"); if (!node->SaveXML(childElem)) return false; } return true; }
bool ValueAnimation::SaveXML(XMLElement& dest) const { dest.SetAttribute("interpolationmethod", interpMethodNames[interpolationMethod_]); if (interpolationMethod_ == IM_SPLINE) dest.SetFloat("splinetension", splineTension_); for (unsigned i = 0; i < keyFrames_.Size(); ++i) { const VAnimKeyFrame& keyFrame = keyFrames_[i]; XMLElement keyFrameEleme = dest.CreateChild("keyframe"); keyFrameEleme.SetFloat("time", keyFrame.time_); keyFrameEleme.SetVariant(keyFrame.value_); } for (unsigned i = 0; i < eventFrames_.Size(); ++i) { const VAnimEventFrame& eventFrame = eventFrames_[i]; XMLElement eventFrameElem = dest.CreateChild("eventframe"); eventFrameElem.SetFloat("time", eventFrame.time_); eventFrameElem.SetUInt("eventtype", eventFrame.eventType_.Value()); eventFrameElem.CreateChild("eventdata").SetVariantMap(eventFrame.eventData_); } return true; }
bool Menu::SaveXML(XMLElement& dest) { // Write type and internal flag if (!dest.SetString("type", GetTypeName())) return false; if (internal_) { if (!dest.SetBool("internal", internal_)) return false; } // Write attributes if (!Serializable::SaveXML(dest)) return false; // Write child elements for (unsigned i = 0; i < children_.Size(); ++i) { UIElement* element = children_[i]; XMLElement childElem = dest.CreateChild("element"); if (!element->SaveXML(childElem)) return false; } // Save the popup element as a "virtual" child element if (popup_) { XMLElement childElem = dest.CreateChild("element"); childElem.SetBool("popup", true); if (!popup_->SaveXML(childElem)) return false; } return true; }
/// Save account information to a file void GameEconomicGameClient::SaveConfiguration(Configuration &configuration) { /// Get Resource ResourceCache * cache = GetSubsystem<ResourceCache>(); FileSystem * fileSystem = GetSubsystem<FileSystem>(); String configFileName; /// Set directory and path for network file configFileName.Append(fileSystem->GetProgramDir().CString()); configFileName.Append(""); configFileName.Append("Configuration.xml"); /// Check if the account file information exist if(fileSystem->FileExists(configFileName.CString())) { fileSystem->Delete(configFileName.CString()); } cout << "It got here "<<endl; File saveFile(context_, configFileName.CString(), FILE_WRITE); XMLFile * preferencefileconfig = new XMLFile(context_); XMLElement configElem = preferencefileconfig -> CreateRoot("Configuration"); XMLElement GameModeConfigurationElement = configElem.CreateChild("GameModeConfiguration"); XMLElement VideoConfigurationElement= configElem.CreateChild("VideoConfiguration"); /// Set true false if(configuration.GameModeForceTablet==true) { GameModeConfigurationElement.SetAttribute("GameModeForceTablet", "true"); } else { GameModeConfigurationElement.SetAttribute("GameModeForceTablet", "false"); } /// Convert video bloom to float String VideoBloomParamValue1String(configuration.VideoBloomParam1); String VideoBloomParamValue2String(configuration.VideoBloomParam2); /// Copy values testing VideoConfigurationElement.SetAttribute("BloomParam1",VideoBloomParamValue1String); VideoConfigurationElement.SetAttribute("BloomParam2",VideoBloomParamValue2String); preferencefileconfig->Save(saveFile); return; }
bool UnknownComponent::SaveXML(XMLElement& dest) const { if (dest.IsNull()) { LOGERROR("Could not save " + GetTypeName() + ", null destination element"); return false; } if (!useXML_) LOGWARNING("UnknownComponent loaded in binary mode, attributes will be empty for XML save"); // Write type and ID if (!dest.SetString("type", GetTypeName())) return false; if (!dest.SetInt("id", id_)) return false; for (unsigned i = 0; i < xmlAttributeInfos_.Size(); ++i) { XMLElement attrElem = dest.CreateChild("attribute"); attrElem.SetAttribute("name", xmlAttributeInfos_[i].name_); attrElem.SetAttribute("value", xmlAttributes_[i]); } return true; }
bool Animation::Save(Serializer& dest) const { // Write ID, name and length dest.WriteFileID("UANI"); dest.WriteString(animationName_); dest.WriteFloat(length_); // Write tracks dest.WriteUInt(tracks_.Size()); for (HashMap<StringHash, AnimationTrack>::ConstIterator i = tracks_.Begin(); i != tracks_.End(); ++i) { const AnimationTrack& track = i->second_; dest.WriteString(track.name_); dest.WriteUByte(track.channelMask_); dest.WriteUInt(track.keyFrames_.Size()); // Write keyframes of the track for (unsigned j = 0; j < track.keyFrames_.Size(); ++j) { const AnimationKeyFrame& keyFrame = track.keyFrames_[j]; dest.WriteFloat(keyFrame.time_); if (track.channelMask_ & CHANNEL_POSITION) dest.WriteVector3(keyFrame.position_); if (track.channelMask_ & CHANNEL_ROTATION) dest.WriteQuaternion(keyFrame.rotation_); if (track.channelMask_ & CHANNEL_SCALE) dest.WriteVector3(keyFrame.scale_); } } // If triggers have been defined, write an XML file for them if (!triggers_.Empty() || HasMetadata()) { File* destFile = dynamic_cast<File*>(&dest); if (destFile) { String xmlName = ReplaceExtension(destFile->GetName(), ".xml"); SharedPtr<XMLFile> xml(new XMLFile(context_)); XMLElement rootElem = xml->CreateRoot("animation"); for (unsigned i = 0; i < triggers_.Size(); ++i) { XMLElement triggerElem = rootElem.CreateChild("trigger"); triggerElem.SetFloat("time", triggers_[i].time_); triggerElem.SetVariant(triggers_[i].data_); } SaveMetadataToXML(rootElem); File xmlFile(context_, xmlName, FILE_WRITE); xml->Save(xmlFile); } else ATOMIC_LOGWARNING("Can not save animation trigger data when not saving into a file"); } return true; }
void ParticleEffect2D::WriteColor(XMLElement& element, const String& name, const Color& color) const { XMLElement child = element.CreateChild(name); child.SetFloat("red", color.r_); child.SetFloat("green", color.g_); child.SetFloat("blue", color.b_); child.SetFloat("alpha", color.a_); }
void CubemapGenerator::SaveCubemapXML() { SharedPtr<XMLFile> xmlFile(new XMLFile(context_)); XMLElement rootElem = xmlFile->CreateRoot("cubemap"); String prefix = resourcePath_ + namePrefix_ + "_"; String name = prefix + GetFaceName(FACE_POSITIVE_X) + ".png"; rootElem.CreateChild("face").SetAttribute("name", name); name = prefix + GetFaceName(FACE_NEGATIVE_X) + ".png"; rootElem.CreateChild("face").SetAttribute("name", name); name = prefix + GetFaceName(FACE_POSITIVE_Y) + ".png"; rootElem.CreateChild("face").SetAttribute("name", name); name = prefix + GetFaceName(FACE_NEGATIVE_Y) + ".png"; rootElem.CreateChild("face").SetAttribute("name", name); name = prefix + GetFaceName(FACE_POSITIVE_Z) + ".png"; rootElem.CreateChild("face").SetAttribute("name", name); name = prefix + GetFaceName(FACE_NEGATIVE_Z) + ".png"; rootElem.CreateChild("face").SetAttribute("name", name); String xmlPath = outputPathAbsolute_ + namePrefix_ + ".xml"; SharedPtr<File> file(new File(context_, xmlPath, FILE_WRITE)); xmlFile->Save(*file, " "); file->Close(); ResourceCache* cache = GetSubsystem<ResourceCache>(); TextureCube* texcube = cache->GetResource<TextureCube>(resourcePath_ + namePrefix_ + ".xml"); if (texcube) cache->ReloadResource(texcube); }
bool Material::Save(XMLElement& dest) const { if (dest.IsNull()) { LOGERROR("Can not save material to null XML element"); return false; } // Write techniques for (unsigned i = 0; i < techniques_.Size(); ++i) { const TechniqueEntry& entry = techniques_[i]; if (!entry.technique_) continue; XMLElement techniqueElem = dest.CreateChild("technique"); techniqueElem.SetString("name", entry.technique_->GetName()); techniqueElem.SetInt("quality", entry.qualityLevel_); techniqueElem.SetFloat("loddistance", entry.lodDistance_); } // Write texture units for (unsigned j = 0; j < MAX_MATERIAL_TEXTURE_UNITS; ++j) { Texture* texture = GetTexture((TextureUnit)j); if (texture) { XMLElement textureElem = dest.CreateChild("texture"); textureElem.SetString("unit", textureUnitNames[j]); textureElem.SetString("name", texture->GetName()); } } // Write shader parameters for (HashMap<StringHash, MaterialShaderParameter>::ConstIterator j = shaderParameters_.Begin(); j != shaderParameters_.End(); ++j) { XMLElement parameterElem = dest.CreateChild("parameter"); parameterElem.SetString("name", j->second_.name_); parameterElem.SetVectorVariant("value", j->second_.value_); } // Write culling modes XMLElement cullElem = dest.CreateChild("cull"); cullElem.SetString("value", cullModeNames[cullMode_]); XMLElement shadowCullElem = dest.CreateChild("shadowcull"); shadowCullElem.SetString("value", cullModeNames[shadowCullMode_]); // Write depth bias XMLElement depthBiasElem = dest.CreateChild("depthbias"); depthBiasElem.SetFloat("constant", depthBias_.constantBias_); depthBiasElem.SetFloat("slopescaled", depthBias_.slopeScaledBias_); return true; }
bool ObjectAnimation::SaveXML(XMLElement& dest) const { for (HashMap<String, SharedPtr<ValueAnimationInfo> >::ConstIterator i = attributeAnimationInfos_.Begin(); i != attributeAnimationInfos_.End(); ++i) { XMLElement animElem = dest.CreateChild("attributeanimation"); animElem.SetAttribute("name", i->first_); const ValueAnimationInfo* info = i->second_; if (!info->GetAnimation()->SaveXML(animElem)) return false; animElem.SetAttribute("wrapmode", wrapModeNames[info->GetWrapMode()]); animElem.SetFloat("speed", info->GetSpeed()); } return true; }
bool SpriteSheet2D::Save(Serializer& dest) const { if (!texture_) return false; SharedPtr<XMLFile> xmlFile(new XMLFile(context_)); XMLElement rootElem = xmlFile->CreateRoot("spritesheet"); rootElem.SetAttribute("texture", texture_->GetName()); for (HashMap<String, SharedPtr<Sprite2D> >::ConstIterator i = spriteMapping_.Begin(); i != spriteMapping_.End(); ++i) { XMLElement spriteElem = rootElem.CreateChild("sprite"); spriteElem.SetAttribute("name", i->first_); Sprite2D* sprite = i->second_; spriteElem.SetIntRect("rectangle", sprite->GetRectangle()); spriteElem.SetVector2("hotspot", sprite->GetHotSpot()); } return xmlFile->Save(dest); }
bool Animation2D::Save(Serializer& dest) const { XMLFile xmlFile(context_); XMLElement rootElem = xmlFile.CreateRoot("Animation"); float endTime = 0.0f; for (unsigned i = 0; i < frameSprites_.Size(); ++i) { XMLElement frameElem = rootElem.CreateChild("Frame"); frameElem.SetFloat("duration", frameEndTimes_[i] - endTime); endTime = frameEndTimes_[i]; Sprite2D* sprite = frameSprites_[i]; SpriteSheet2D* spriteSheet = sprite->GetSpriteSheet(); if (!spriteSheet) frameElem.SetString("sprite", sprite->GetName()); else frameElem.SetString("sprite", spriteSheet->GetName() + "@" + sprite->GetName()); } return xmlFile.Save(dest); }
bool Menu::SaveXML(XMLElement& dest) const { if (!Button::SaveXML(dest)) return false; // Save the popup element as a "virtual" child element if (popup_) { XMLElement childElem = dest.CreateChild("element"); childElem.SetBool("popup", true); if (!popup_->SaveXML(childElem)) return false; // Filter popup implicit attributes if (!FilterPopupImplicitAttributes(childElem)) { URHO3D_LOGERROR("Could not remove popup implicit attributes"); return false; } } return true; }
bool ParticleEffect::Save(XMLElement& dest) const { if (dest.IsNull()) { URHO3D_LOGERROR("Can not save particle effect to null XML element"); return false; } XMLElement childElem = dest.CreateChild("material"); childElem.SetAttribute("name", GetResourceName(material_)); childElem = dest.CreateChild("numparticles"); childElem.SetInt("value", numParticles_); childElem = dest.CreateChild("updateinvisible"); childElem.SetBool("enable", updateInvisible_); childElem = dest.CreateChild("relative"); childElem.SetBool("enable", relative_); childElem = dest.CreateChild("scaled"); childElem.SetBool("enable", scaled_); childElem = dest.CreateChild("sorted"); childElem.SetBool("enable", sorted_); childElem = dest.CreateChild("fixedscreensize"); childElem.SetBool("enable", fixedScreenSize_); childElem = dest.CreateChild("animlodbias"); childElem.SetFloat("value", animationLodBias_); childElem = dest.CreateChild("emittertype"); childElem.SetAttribute("value", emitterTypeNames[emitterType_]); childElem = dest.CreateChild("emittersize"); childElem.SetVector3("value", emitterSize_); childElem = dest.CreateChild("direction"); childElem.SetVector3("min", directionMin_); childElem.SetVector3("max", directionMax_); childElem = dest.CreateChild("constantforce"); childElem.SetVector3("value", constantForce_); childElem = dest.CreateChild("dampingforce"); childElem.SetFloat("value", dampingForce_); childElem = dest.CreateChild("activetime"); childElem.SetFloat("value", activeTime_); childElem = dest.CreateChild("inactivetime"); childElem.SetFloat("value", inactiveTime_); childElem = dest.CreateChild("emissionrate"); childElem.SetFloat("min", emissionRateMin_); childElem.SetFloat("max", emissionRateMax_); childElem = dest.CreateChild("particlesize"); childElem.SetVector2("min", sizeMin_); childElem.SetVector2("max", sizeMax_); childElem = dest.CreateChild("timetolive"); childElem.SetFloat("min", timeToLiveMin_); childElem.SetFloat("max", timeToLiveMax_); childElem = dest.CreateChild("velocity"); childElem.SetFloat("min", velocityMin_); childElem.SetFloat("max", velocityMax_); childElem = dest.CreateChild("rotation"); childElem.SetFloat("min", rotationMin_); childElem.SetFloat("max", rotationMax_); childElem = dest.CreateChild("rotationspeed"); childElem.SetFloat("min", rotationSpeedMin_); childElem.SetFloat("max", rotationSpeedMax_); childElem = dest.CreateChild("sizedelta"); childElem.SetFloat("add", sizeAdd_); childElem.SetFloat("mul", sizeMul_); childElem = dest.CreateChild("faceCameraMode"); childElem.SetAttribute("value", faceCameraModeNames[faceCameraMode_]); if (colorFrames_.Size() == 1) { childElem = dest.CreateChild("color"); childElem.SetColor("value", colorFrames_[0].color_); } if (colorFrames_.Size() > 1) { for (unsigned i = 0; i < colorFrames_.Size(); ++i) { childElem = dest.CreateChild("colorfade"); childElem.SetColor("color", colorFrames_[i].color_); childElem.SetFloat("time", colorFrames_[i].time_); } } for (unsigned i = 0; i < textureFrames_.Size(); ++i) { childElem = dest.CreateChild("texanim"); childElem.SetRect("uv", textureFrames_[i].uv_); childElem.SetFloat("time", textureFrames_[i].time_); } return true; }
bool ParticleEffect2D::Save(Serializer& dest) const { if (!sprite_) return false; XMLFile xmlFile(context_); XMLElement rootElem = xmlFile.CreateRoot("particleEmitterConfig"); String fileName = GetFileNameAndExtension(sprite_->GetName()); rootElem.CreateChild("texture").SetAttribute("name", fileName); WriteVector2(rootElem, "sourcePosition", Vector2::ZERO); WriteVector2(rootElem, "sourcePositionVariance", sourcePositionVariance_); WriteFloat(rootElem, "speed", speed_); WriteFloat(rootElem, "speedVariance", speedVariance_); WriteFloat(rootElem, "particleLifeSpan", particleLifeSpan_); WriteFloat(rootElem, "particleLifespanVariance", particleLifespanVariance_); WriteFloat(rootElem, "angle", angle_); WriteFloat(rootElem, "angleVariance", angleVariance_); WriteVector2(rootElem, "gravity", gravity_); WriteFloat(rootElem, "radialAcceleration", radialAcceleration_); WriteFloat(rootElem, "tangentialAcceleration", tangentialAcceleration_); WriteFloat(rootElem, "radialAccelVariance", radialAccelVariance_); WriteFloat(rootElem, "tangentialAccelVariance", tangentialAccelVariance_); WriteColor(rootElem, "startColor", startColor_); WriteColor(rootElem, "startColorVariance", startColorVariance_); WriteColor(rootElem, "finishColor", finishColor_); WriteColor(rootElem, "finishColorVariance", finishColorVariance_); WriteInt(rootElem, "maxParticles", maxParticles_); WriteFloat(rootElem, "startParticleSize", startParticleSize_); WriteFloat(rootElem, "startParticleSizeVariance", startParticleSizeVariance_); WriteFloat(rootElem, "finishParticleSize", finishParticleSize_); // Typo in pex file WriteFloat(rootElem, "FinishParticleSizeVariance", FinishParticleSizeVariance_); float duration = duration_; if (duration == M_INFINITY) duration = -1.0f; WriteFloat(rootElem, "duration", duration); WriteInt(rootElem, "emitterType", (int)emitterType_); WriteFloat(rootElem, "maxRadius", maxRadius_); WriteFloat(rootElem, "maxRadiusVariance", maxRadiusVariance_); WriteFloat(rootElem, "minRadius", minRadius_); WriteFloat(rootElem, "minRadiusVariance", minRadiusVariance_); WriteFloat(rootElem, "rotatePerSecond", rotatePerSecond_); WriteFloat(rootElem, "rotatePerSecondVariance", rotatePerSecondVariance_); WriteInt(rootElem, "blendFuncSource", srcBlendFuncs[blendMode_]); WriteInt(rootElem, "blendFuncDestination", destBlendFuncs[blendMode_]); WriteFloat(rootElem, "rotationStart", rotationStart_); WriteFloat(rootElem, "rotationStartVariance", rotationStartVariance_); WriteFloat(rootElem, "rotationEnd", rotationEnd_); WriteFloat(rootElem, "rotationEndVariance", rotationEndVariance_); return xmlFile.Save(dest); }
void ParticleEffect2D::WriteFloat(XMLElement& element, const String& name, float value) const { XMLElement child = element.CreateChild(name); child.SetFloat("value", value); }
void ParticleEffect2D::WriteVector2(XMLElement& element,const String& name,const Vector2& value) const { XMLElement child = element.CreateChild(name); child.SetFloat("x", value.x_); child.SetFloat("y", value.y_); }
void Run(Vector<String>& arguments) { if (arguments.Size() < 2) Help(); SharedPtr<Context> context(new Context()); context->RegisterSubsystem(new FileSystem(context)); context->RegisterSubsystem(new Log(context)); FileSystem* fileSystem = context->GetSubsystem<FileSystem>(); Vector<String> inputFiles; String outputFile; String spriteSheetFileName; bool debug = false; unsigned padX = 0; unsigned padY = 0; unsigned offsetX = 0; unsigned offsetY = 0; unsigned frameWidth = 0; unsigned frameHeight = 0; bool help = false; bool trim = false; while (arguments.Size() > 0) { String arg = arguments[0]; arguments.Erase(0); if (arg.Empty()) continue; if (arg.StartsWith("-")) { if (arg == "-px") { padX = ToUInt(arguments[0]); arguments.Erase(0); } else if (arg == "-py") { padY = ToUInt(arguments[0]); arguments.Erase(0); } else if (arg == "-ox") { offsetX = ToUInt(arguments[0]); arguments.Erase(0); } else if (arg == "-oy") { offsetY = ToUInt(arguments[0]); arguments.Erase(0); } else if (arg == "-frameWidth") { frameWidth = ToUInt(arguments[0]); arguments.Erase(0); } else if (arg == "-frameHeight") { frameHeight = ToUInt(arguments[0]); arguments.Erase(0); } else if (arg == "-trim") { trim = true; } else if (arg == "-xml") { spriteSheetFileName = arguments[0]; arguments.Erase(0); } else if (arg == "-h") { help = true; break; } else if (arg == "-debug") { debug = true; } } else inputFiles.Push(arg); } if (help) Help(); if (inputFiles.Size() < 2) ErrorExit("An input and output file must be specified."); if (frameWidth ^ frameHeight) ErrorExit("Both frameHeight and frameWidth must be ommited or specified."); // take last input file as output if (inputFiles.Size() > 1) { outputFile = inputFiles[inputFiles.Size() - 1]; LOGINFO("Output file set to " + outputFile + "."); inputFiles.Erase(inputFiles.Size() - 1); } // set spritesheet name to outputfile.xml if not specified if (spriteSheetFileName.Empty()) spriteSheetFileName = ReplaceExtension(outputFile, ".xml"); if (GetParentPath(spriteSheetFileName) != GetParentPath(outputFile)) ErrorExit("Both output xml and png must be in the same folder"); // check all input files exist for (unsigned i = 0; i < inputFiles.Size(); ++i) { LOGINFO("Checking " + inputFiles[i] + " to see if file exists."); if (!fileSystem->FileExists(inputFiles[i])) ErrorExit("File " + inputFiles[i] + " does not exist."); } // Set the max offset equal to padding to prevent images from going out of bounds offsetX = Min((int)offsetX, (int)padX); offsetY = Min((int)offsetY, (int)padY); Vector<SharedPtr<PackerInfo > > packerInfos; for (unsigned i = 0; i < inputFiles.Size(); ++i) { String path = inputFiles[i]; String name = ReplaceExtension(GetFileName(path), ""); File file(context, path); Image image(context); if (!image.Load(file)) ErrorExit("Could not load image " + path + "."); if (image.IsCompressed()) ErrorExit(path + " is compressed. Compressed images are not allowed."); SharedPtr<PackerInfo> packerInfo(new PackerInfo(path, name)); int imageWidth = image.GetWidth(); int imageHeight = image.GetHeight(); int trimOffsetX = 0; int trimOffsetY = 0; int adjustedWidth = imageWidth; int adjustedHeight = imageHeight; if (trim) { int minX = imageWidth; int minY = imageHeight; int maxX = 0; int maxY = 0; for (int y = 0; y < imageHeight; ++y) { for (int x = 0; x < imageWidth; ++x) { bool found = (image.GetPixelInt(x, y) & 0x000000ff) != 0; if (found) { minX = Min(minX, x); minY = Min(minY, y); maxX = Max(maxX, x); maxY = Max(maxY, y); } } } trimOffsetX = minX; trimOffsetY = minY; adjustedWidth = maxX - minX + 1; adjustedHeight = maxY - minY + 1; } if (trim) { packerInfo->frameWidth = imageWidth; packerInfo->frameHeight = imageHeight; } else if (frameWidth || frameHeight) { packerInfo->frameWidth = frameWidth; packerInfo->frameHeight = frameHeight; } packerInfo->width = adjustedWidth; packerInfo->height = adjustedHeight; packerInfo->offsetX -= trimOffsetX; packerInfo->offsetY -= trimOffsetY; packerInfos.Push(packerInfo); } int packedWidth = MAX_TEXTURE_SIZE; int packedHeight = MAX_TEXTURE_SIZE; { // fill up an list of tries in increasing size and take the first win Vector<IntVector2> tries; for(unsigned x=2; x<11; ++x) { for(unsigned y=2; y<11; ++y) tries.Push(IntVector2((1<<x), (1<<y))); } // load rectangles stbrp_rect* packerRects = new stbrp_rect[packerInfos.Size()]; for (unsigned i = 0; i < packerInfos.Size(); ++i) { PackerInfo* packerInfo = packerInfos[i]; stbrp_rect* packerRect = &packerRects[i]; packerRect->id = i; packerRect->h = packerInfo->height + padY; packerRect->w = packerInfo->width + padX; } bool success = false; while (tries.Size() > 0) { IntVector2 size = tries[0]; tries.Erase(0); bool fit = true; int textureHeight = size.y_; int textureWidth = size.x_; if (success && textureHeight * textureWidth > packedWidth * packedHeight) continue; stbrp_context packerContext; stbrp_node packerMemory[PACKER_NUM_NODES]; stbrp_init_target(&packerContext, textureWidth, textureHeight, packerMemory, packerInfos.Size()); stbrp_pack_rects(&packerContext, packerRects, packerInfos.Size()); // check to see if everything fit for (unsigned i = 0; i < packerInfos.Size(); ++i) { stbrp_rect* packerRect = &packerRects[i]; if (!packerRect->was_packed) { fit = false; break; } } if (fit) { success = true; // distribute values to packer info for (unsigned i = 0; i < packerInfos.Size(); ++i) { stbrp_rect* packerRect = &packerRects[i]; PackerInfo* packerInfo = packerInfos[packerRect->id]; packerInfo->x = packerRect->x; packerInfo->y = packerRect->y; } packedWidth = size.x_; packedHeight = size.y_; } } delete packerRects; if (!success) ErrorExit("Could not allocate for all images. The max sprite sheet texture size is " + String(MAX_TEXTURE_SIZE) + "x" + String(MAX_TEXTURE_SIZE) + "."); } // create image for spritesheet Image spriteSheetImage(context); spriteSheetImage.SetSize(packedWidth, packedHeight, 4); // zero out image spriteSheetImage.SetData((unsigned char*)calloc(sizeof(unsigned char), packedWidth * packedHeight * 4)); XMLFile xml(context); XMLElement root = xml.CreateRoot("TextureAtlas"); root.SetAttribute("imagePath", GetFileNameAndExtension(outputFile)); for (unsigned i = 0; i < packerInfos.Size(); ++i) { SharedPtr<PackerInfo> packerInfo = packerInfos[i]; XMLElement subTexture = root.CreateChild("SubTexture"); subTexture.SetString("name", packerInfo->name); subTexture.SetInt("x", packerInfo->x + offsetX); subTexture.SetInt("y", packerInfo->y + offsetY); subTexture.SetInt("width", packerInfo->width); subTexture.SetInt("height", packerInfo->height); if (packerInfo->frameWidth || packerInfo->frameHeight) { subTexture.SetInt("frameWidth", packerInfo->frameWidth); subTexture.SetInt("frameHeight", packerInfo->frameHeight); subTexture.SetInt("offsetX", packerInfo->offsetX); subTexture.SetInt("offsetY", packerInfo->offsetY); } LOGINFO("Transfering " + packerInfo->path + " to sprite sheet."); File file(context, packerInfo->path); Image image(context); if (!image.Load(file)) ErrorExit("Could not load image " + packerInfo->path + "."); for (int y = 0; y < packerInfo->height; ++y) { for (int x = 0; x < packerInfo->width; ++x) { unsigned color = image.GetPixelInt(x - packerInfo->offsetX, y - packerInfo->offsetY); spriteSheetImage.SetPixelInt( packerInfo->x + offsetX + x, packerInfo->y + offsetY + y, color); } } } if (debug) { unsigned OUTER_BOUNDS_DEBUG_COLOR = Color::BLUE.ToUInt(); unsigned INNER_BOUNDS_DEBUG_COLOR = Color::GREEN.ToUInt(); LOGINFO("Drawing debug information."); for (unsigned i = 0; i < packerInfos.Size(); ++i) { SharedPtr<PackerInfo> packerInfo = packerInfos[i]; // Draw outer bounds for (int x = 0; x < packerInfo->frameWidth; ++x) { spriteSheetImage.SetPixelInt(packerInfo->x + x, packerInfo->y, OUTER_BOUNDS_DEBUG_COLOR); spriteSheetImage.SetPixelInt(packerInfo->x + x, packerInfo->y + packerInfo->frameHeight, OUTER_BOUNDS_DEBUG_COLOR); } for (int y = 0; y < packerInfo->frameHeight; ++y) { spriteSheetImage.SetPixelInt(packerInfo->x, packerInfo->y + y, OUTER_BOUNDS_DEBUG_COLOR); spriteSheetImage.SetPixelInt(packerInfo->x + packerInfo->frameWidth, packerInfo->y + y, OUTER_BOUNDS_DEBUG_COLOR); } // Draw inner bounds for (int x = 0; x < packerInfo->width; ++x) { spriteSheetImage.SetPixelInt(packerInfo->x + offsetX + x, packerInfo->y + offsetY, INNER_BOUNDS_DEBUG_COLOR); spriteSheetImage.SetPixelInt(packerInfo->x + offsetX + x, packerInfo->y + offsetY + packerInfo->height, INNER_BOUNDS_DEBUG_COLOR); } for (int y = 0; y < packerInfo->height; ++y) { spriteSheetImage.SetPixelInt(packerInfo->x + offsetX, packerInfo->y + offsetY + y, INNER_BOUNDS_DEBUG_COLOR); spriteSheetImage.SetPixelInt(packerInfo->x + offsetX + packerInfo->width, packerInfo->y + offsetY + y, INNER_BOUNDS_DEBUG_COLOR); } } } LOGINFO("Saving output image."); spriteSheetImage.SavePNG(outputFile); LOGINFO("Saving SpriteSheet xml file."); File spriteSheetFile(context); spriteSheetFile.Open(spriteSheetFileName, FILE_WRITE); xml.Save(spriteSheetFile); }
bool Font::SaveXML(Serializer& dest, int pointSize, bool usedGlyphs) { const FontFace* fontFace = GetFace(pointSize); if (!fontFace) return false; PROFILE(FontSaveXML); SharedPtr<FontFace> packedFontFace; if (usedGlyphs) { // Save used glyphs only, try to pack them first packedFontFace = Pack(fontFace); if (packedFontFace) fontFace = packedFontFace; else return false; } SharedPtr<XMLFile> xml(new XMLFile(context_)); XMLElement rootElem = xml->CreateRoot("font"); // Information XMLElement childElem = rootElem.CreateChild("info"); String fileName = GetFileName(GetName()); childElem.SetAttribute("face", fileName); childElem.SetAttribute("size", String(pointSize)); // Common childElem = rootElem.CreateChild("common"); childElem.SetInt("lineHeight", fontFace->rowHeight_); unsigned pages = fontFace->textures_.Size(); childElem.SetInt("pages", pages); // Construct the path to store the texture String pathName; File* file = dynamic_cast<File*>(&dest); if (file) // If serialize to file, use the file's path pathName = GetPath(file->GetName()); else // Otherwise, use the font resource's path pathName = "Data/" + GetPath(GetName()); // Pages childElem = rootElem.CreateChild("pages"); for (unsigned i = 0; i < pages; ++i) { XMLElement pageElem = childElem.CreateChild("page"); pageElem.SetInt("id", i); String texFileName = fileName + "_" + String(i) + ".png"; pageElem.SetAttribute("file", texFileName); // Save the font face texture to image file SaveFaceTexture(fontFace->textures_[i], pathName + texFileName); } // Chars and kernings XMLElement charsElem = rootElem.CreateChild("chars"); unsigned numGlyphs = fontFace->glyphs_.Size(); charsElem.SetInt("count", numGlyphs); XMLElement kerningsElem; bool hasKerning = fontFace->hasKerning_; if (hasKerning) kerningsElem = rootElem.CreateChild("kernings"); for (HashMap<unsigned, unsigned>::ConstIterator i = fontFace->glyphMapping_.Begin(); i != fontFace->glyphMapping_.End(); ++i) { // Char XMLElement charElem = charsElem.CreateChild("char"); charElem.SetInt("id", i->first_); FontGlyph glyph = fontFace->glyphs_[i->second_]; charElem.SetInt("x", glyph.x_); charElem.SetInt("y", glyph.y_); charElem.SetInt("width", glyph.width_); charElem.SetInt("height", glyph.height_); charElem.SetInt("xoffset", glyph.offsetX_); charElem.SetInt("yoffset", glyph.offsetY_); charElem.SetInt("xadvance", glyph.advanceX_); charElem.SetInt("page", glyph.page_); // Kerning if (hasKerning) { for (HashMap<unsigned, unsigned>::ConstIterator j = glyph.kerning_.Begin(); j != glyph.kerning_.End(); ++j) { // To conserve space, only write when amount is non zero if (j->second_ == 0) continue; XMLElement kerningElem = kerningsElem.CreateChild("kerning"); kerningElem.SetInt("first", i->first_); kerningElem.SetInt("second", j->first_); kerningElem.SetInt("amount", j->second_); } } } return xml->Save(dest); }