bool hkvTextureTransformationRule::executeTransformation(const hkvTransformationInput& input, hkvTransformationOutput& output) const { Context context(input, output); bool ok = !context.m_canceled && (transferSourceProperties(context) == HK_SUCCESS); ok = ok && !context.m_canceled && (examineSourceFile(context) == HK_SUCCESS); ok = ok && !context.m_canceled && (determineOutputs(context) == HK_SUCCESS); ok = ok && !context.m_canceled && (makeIntermediateBaseName(context) == HK_SUCCESS); ok = ok && !context.m_canceled && (copySourceFileToTemp(context) == HK_SUCCESS); int numVariants = context.m_outputVariants.getSize(); for (int variantIdx = 0; ok && (variantIdx < numVariants); ++variantIdx) { const hkvTextureVariant& variant = context.m_outputVariants[variantIdx]; ok = ok && !context.m_canceled && (prepareTransformationSettings(context, variant) == HK_SUCCESS); if (ok && hkvFileHelper::fileExists(context.m_targetFile)) { continue; } ok = ok && !context.m_canceled && (runConversion(context) == HK_SUCCESS); ok = ok && !context.m_canceled && (moveTempFileToTarget(context) == HK_SUCCESS); if (ok) { notifyOutputWritten(context, variant.m_variantKey.cString()); } } cleanUpTempFiles(context); if (ok) { context.m_output.m_messages.pushBack(hkvAssetLogMessage( HKV_MESSAGE_CATEGORY_ASSET_TRANSFORMATION, HKV_MESSAGE_SEVERITY_INFO, "Texture transformed successfully.")); } else if (context.m_canceled) { deleteTargetFile(context); context.m_output.m_messages.pushBack(hkvAssetLogMessage( HKV_MESSAGE_CATEGORY_ASSET_TRANSFORMATION, HKV_MESSAGE_SEVERITY_WARNING, "Transformation of texture was canceled.")); } else { context.m_output.m_messages.pushBack(hkvAssetLogMessage( HKV_MESSAGE_CATEGORY_ASSET_TRANSFORMATION, HKV_MESSAGE_SEVERITY_ERROR, "Transformation of texture failed!")); } return ok; }
bool hkvTextureTransformationSettings::checkFormatCompatibility( hkArray<hkvAssetLogMessage>& out_messages) { // Check if the file and data formats are compatible if (!hkvTextureFileToDataFormatMapping::getInstance().isMapped(m_targetFileFormat, m_targetDataFormat)) { hkStringBuf msg; msg.printf("The target file format (%s) is not compatible with the target data format (%s)", hkvTextureFileFormatNames[m_targetFileFormat], hkvTextureDataFormatNames[m_targetDataFormat]); out_messages.pushBack(hkvAssetLogMessage(HKV_MESSAGE_CATEGORY_ASSET_TRANSFORMATION, HKV_MESSAGE_SEVERITY_ERROR, msg)); } // Check if the platform can handle the target data format if (m_platform != HKV_TARGET_PLATFORM_ANY) { if (!hkvPlatformToTextureDataFormatMapping::getInstance().isMapped(m_platform, m_targetDataFormat)) { const char* platformName = ""; hkvGetTargetPlatformDefinition().idToString(m_platform, platformName); hkStringBuf msg; msg.printf("The target data format (%s) is not compatible with the target platform (%s)", hkvTextureDataFormatNames[m_targetDataFormat], platformName); out_messages.pushBack(hkvAssetLogMessage(HKV_MESSAGE_CATEGORY_ASSET_TRANSFORMATION, HKV_MESSAGE_SEVERITY_ERROR, msg)); } } // Check if the platform can handle the target file format if (m_platform != HKV_TARGET_PLATFORM_ANY) { if (!hkvPlatformToTextureFileFormatMapping::getInstance().isMapped(m_platform, m_targetFileFormat)) { const char* platformName = ""; hkvGetTargetPlatformDefinition().idToString(m_platform, platformName); hkStringBuf msg; msg.printf("The target file format (%s) is not compatible with the target platform (%s)", hkvTextureFileFormatNames[m_targetFileFormat], platformName); out_messages.pushBack(hkvAssetLogMessage(HKV_MESSAGE_CATEGORY_ASSET_TRANSFORMATION, HKV_MESSAGE_SEVERITY_ERROR, msg)); } } return true; }
bool hkvTextureTransformationSettings::ensureDimensionIntegrity(hkArray<hkvAssetLogMessage>& out_messages) { if (m_sourceWidth == 0 || m_sourceHeight == 0) { out_messages.pushBack(hkvAssetLogMessage(HKV_MESSAGE_CATEGORY_ASSET_TRANSFORMATION, HKV_MESSAGE_SEVERITY_ERROR, "Size of source texture is invalid; cannot continue!")); return false; } // Perform sanity checks if (m_validationNeedsPowerOfTwo && m_validationNeedsMultipleOf > 1) { if (hkvMath::isPowerOf2(m_validationNeedsMultipleOf)) { // Both Power-of-Two and Multiple-of restrictions are given. However, multiple-of is a power of two, // so we can drop the multiple-of constraint as long as we limit the minimum size. m_validationMinSize = hkvMath::Max(m_validationMinSize, m_validationNeedsMultipleOf); } else { VASSERT_MSG(false, "Both Power-of-Two and Multiple-of restrictions are specified, but Multiple-of is not a power of two. Ignoring Multiple-of."); } m_validationNeedsMultipleOf = 1; } if (m_validationNeedsPowerOfTwo) { if (m_validationMinSize > 0 && !hkvMath::isPowerOf2(m_validationMinSize)) { VASSERT_MSG(false, "According to set restrictions, system minimum size needs to be Power-of-Two. Adjusting."); m_validationMinSize = hkvMath::powerOf2_ceil(m_validationMinSize); } if (m_userMinSize > 0) { m_userMinSize = adjustToNearestPowerOfTwo(m_userMinSize); } if (m_validationMaxSize > 0 && !hkvMath::isPowerOf2(m_validationMaxSize)) { VASSERT_MSG(false, "According to set restrictions, system maximum size needs to be Power-of-Two. Adjusting."); m_validationMaxSize = hkvMath::powerOf2_floor(m_validationMaxSize); } if (m_userMaxSize > 0) { m_userMaxSize = adjustToNearestPowerOfTwo(m_userMaxSize); } } if (m_validationNeedsMultipleOf > 1) { if ((m_validationMinSize % m_validationNeedsMultipleOf) != 0) { VASSERT_MSG(false, "According to set restrictions, system minimum size needs to be Multiple-of. Adjusting."); m_validationMinSize = ((m_validationMinSize + m_validationNeedsMultipleOf - 1) / m_validationNeedsMultipleOf) * m_validationNeedsMultipleOf; } m_userMinSize = ((m_userMinSize + m_validationNeedsMultipleOf - 1) / m_validationNeedsMultipleOf) * m_validationNeedsMultipleOf; if (m_validationMaxSize % m_validationNeedsMultipleOf != 0) { VASSERT_MSG(false, "According to set restrictions, system maximum size needs to be Multiple-of. Adjusting."); m_validationMaxSize = (m_validationMaxSize / m_validationNeedsMultipleOf) * m_validationNeedsMultipleOf; } m_userMaxSize = (m_userMaxSize / m_validationNeedsMultipleOf) * m_validationNeedsMultipleOf; } if ((m_validationMinSize > 0) && (m_validationMaxSize > 0) && (m_validationMaxSize < m_validationMinSize)) { VASSERT_MSG(false, "System maximum size less than system minimum size; adjusting."); m_validationMinSize = m_validationMaxSize; } if ((m_userMinSize > 0) && (m_userMaxSize > 0) && (m_userMaxSize < m_userMinSize)) { m_userMinSize = m_userMaxSize; } if ((m_validationMinSize > 0) && (m_userMinSize > 0) && (m_userMinSize < m_validationMinSize)) { m_userMinSize = m_validationMinSize; } if ((m_validationMaxSize > 0) && (m_userMaxSize > 0) && (m_userMaxSize > m_validationMaxSize)) { m_userMaxSize = m_validationMaxSize; } return true; }
hkResult hkvTextureTransformationRule::runConversion(Context& context) const { context.m_stepSourceFile = context.m_tempOriginalFile; int numSteps = context.m_transformationSteps.getSize(); for (int stepIdx = 0; stepIdx < numSteps; ++stepIdx) { TransformationStepInfo& stepInfo = context.m_transformationSteps[stepIdx]; // Check if this step's transformation settings are valid. If not, try to validate them. hkvTextureTransformationSettings& settings = stepInfo.getSettings(); if (!settings.isValid() && (settings.validate(context.m_output.m_messages) != HK_SUCCESS)) { context.m_output.m_messages.pushBack(hkvAssetLogMessage( HKV_MESSAGE_CATEGORY_ASSET_TRANSFORMATION, HKV_MESSAGE_SEVERITY_ERROR, "Failed to validate transformation settings of a transformation step!")); return HK_FAILURE; } // If this is not the first step, take the output of the previous step as the // input of this step if (stepIdx > 0) { context.m_stepSourceFile = context.m_stepTargetFile; } // The new output file name is a generated base name with the step-specific extension hkStringBuf nameBuf; context.m_stepTargetFile = makeIntermediateFileName(context, stepInfo.getTargetExtension(), nameBuf); hkRefPtr<hkvFileTransformationStep> step; switch (stepInfo.getStepType()) { case STEP_TYPE_WIIU_TEXCONV2: { step = hkRefNew<hkvFileTransformationStep>( new hkvExternalToolWiiUTexConv2(stepInfo.getSettings(), context.m_stepSourceFile, context.m_stepTargetFile)); break; } case STEP_TYPE_IMAGE_TO_DDS: { step = hkRefPtr<hkvFileTransformationStep>( new hkvTransformationStepImageToDds(stepInfo.getSettings(), context.m_stepSourceFile, context.m_stepTargetFile)); break; } case STEP_TYPE_PVRTEXTOOL: { step = hkRefNew<hkvFileTransformationStep>( new hkvExternalToolPvrTexTool(stepInfo.getSettings(), context.m_stepSourceFile, context.m_stepTargetFile)); break; } case STEP_TYPE_TEXCONV: { step = hkRefNew<hkvFileTransformationStep>( new hkvExternalToolTexConv(stepInfo.getSettings(), context.m_stepSourceFile, context.m_stepTargetFile, false)); break; } case STEP_TYPE_TEXCONV_FORCE_DXT10: { step = hkRefNew<hkvFileTransformationStep>( new hkvExternalToolTexConv(stepInfo.getSettings(), context.m_stepSourceFile, context.m_stepTargetFile, true)); break; } default: { VASSERT_MSG(FALSE, "Missing tool case!"); return HK_FAILURE; } } // Some tools want to create output files with a name of their choosing. Now that we // know the concrete step to execute, query it for its output file name. context.m_stepTargetFile = step->getTargetFile(); context.m_tempFileNames.pushBack(context.m_stepTargetFile); { hkvCriticalSectionLock lock(s_protect); context.m_currentTransformationStep = step; } hkResult stepResult = step->run(); { hkvCriticalSectionLock lock(s_protect); context.m_currentTransformationStep = NULL; } context.m_output.m_messages.append(step->getMessages()); if (stepResult != HK_SUCCESS) { if (context.m_canceled) { context.m_output.m_messages.pushBack(hkvAssetLogMessage( HKV_MESSAGE_CATEGORY_ASSET_TRANSFORMATION, HKV_MESSAGE_SEVERITY_WARNING, "Transformation step was canceled.")); } else { context.m_output.m_messages.pushBack(hkvAssetLogMessage( HKV_MESSAGE_CATEGORY_ASSET_TRANSFORMATION, HKV_MESSAGE_SEVERITY_ERROR, "Transformation step failed!")); } return HK_FAILURE; } } return HK_SUCCESS; }