/* * Copyright (c) <2021> Side Effects Software Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * 1. Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * 2. The name of Side Effects Software may not be used to endorse or * promote products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY SIDE EFFECTS SOFTWARE "AS IS" AND ANY EXPRESS * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN * NO EVENT SHALL SIDE EFFECTS SOFTWARE BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "HoudiniPublicAPI.h" #include "HoudiniAsset.h" #include "HoudiniEngineEditorUtils.h" #include "HoudiniPublicAPIAssetWrapper.h" #include "HoudiniPublicAPIInputTypes.h" #include "HoudiniEngineCommands.h" UHoudiniPublicAPI::UHoudiniPublicAPI() { } bool UHoudiniPublicAPI::IsSessionValid_Implementation() const { return FHoudiniEngineCommands::IsSessionValid(); } void UHoudiniPublicAPI::CreateSession_Implementation() { if (!IsSessionValid()) FHoudiniEngineCommands::CreateSession(); } void UHoudiniPublicAPI::StopSession_Implementation() { if (IsSessionValid()) FHoudiniEngineCommands::StopSession(); } void UHoudiniPublicAPI::RestartSession_Implementation() { if (IsSessionValid()) FHoudiniEngineCommands::RestartSession(); else FHoudiniEngineCommands::CreateSession(); } UHoudiniPublicAPIAssetWrapper* UHoudiniPublicAPI::InstantiateAsset_Implementation( UHoudiniAsset* InHoudiniAsset, const FTransform& InInstantiateAt, UObject* InWorldContextObject, ULevel* InSpawnInLevelOverride, const bool bInEnableAutoCook, const bool bInEnableAutoBake, const FString& InBakeDirectoryPath, const EHoudiniEngineBakeOption InBakeMethod, const bool bInRemoveOutputAfterBake, const bool bInRecenterBakedActors, const bool bInReplacePreviousBake) { if (!IsValid(InHoudiniAsset) || !(InHoudiniAsset->AssetImportData)) { SetErrorMessage(TEXT("InHoudiniAsset is invalid or does not have AssetImportData.")); return nullptr; } // Create wrapper for asset instance UHoudiniPublicAPIAssetWrapper* Wrapper = UHoudiniPublicAPIAssetWrapper::CreateEmptyWrapper(this); if (Wrapper) { // Enable/disable error logging based on the API setting Wrapper->SetLoggingErrorsEnabled(IsLoggingErrors()); if (!InstantiateAssetWithExistingWrapper( Wrapper, InHoudiniAsset, InInstantiateAt, InWorldContextObject, InSpawnInLevelOverride, bInEnableAutoCook, bInEnableAutoBake, InBakeDirectoryPath, InBakeMethod, bInRemoveOutputAfterBake, bInRecenterBakedActors, bInReplacePreviousBake)) { // failed to instantiate asset, return null return nullptr; } } return Wrapper; } bool UHoudiniPublicAPI::InstantiateAssetWithExistingWrapper_Implementation( UHoudiniPublicAPIAssetWrapper* InWrapper, UHoudiniAsset* InHoudiniAsset, const FTransform& InInstantiateAt, UObject* InWorldContextObject, ULevel* InSpawnInLevelOverride, const bool bInEnableAutoCook, const bool bInEnableAutoBake, const FString& InBakeDirectoryPath, const EHoudiniEngineBakeOption InBakeMethod, const bool bInRemoveOutputAfterBake, const bool bInRecenterBakedActors, const bool bInReplacePreviousBake) { if (!IsValid(InWrapper)) { SetErrorMessage(TEXT("InWrapper is not valid.")); return false; } if (!IsValid(InHoudiniAsset) || !(InHoudiniAsset->AssetImportData)) { SetErrorMessage(TEXT("InHoudiniAsset is invalid or does not have AssetImportData.")); return false; } UWorld* OverrideWorldToSpawnIn = IsValid(InWorldContextObject) ? InWorldContextObject->GetWorld() : nullptr; AActor* HoudiniAssetActor = FHoudiniEngineEditorUtils::InstantiateHoudiniAssetAt(InHoudiniAsset, InInstantiateAt, OverrideWorldToSpawnIn, InSpawnInLevelOverride); if (!IsValid(HoudiniAssetActor)) { // Determine the path of what would have been the owning level/world of the actor for error logging purposes const FString LevelPath = IsValid(InSpawnInLevelOverride) ? InSpawnInLevelOverride->GetPathName() : FString(); const FString WorldPath = IsValid(OverrideWorldToSpawnIn) ? OverrideWorldToSpawnIn->GetPathName() : FString(); const FString OwnerPath = LevelPath.IsEmpty() ? WorldPath : LevelPath; SetErrorMessage(FString::Printf(TEXT("Failed to spawn a AHoudiniAssetActor in %s."), *OwnerPath)); return false; } // Wrap the instantiated asset if (!InWrapper->WrapHoudiniAssetObject(HoudiniAssetActor)) { FString WrapperError; InWrapper->GetLastErrorMessage(WrapperError); SetErrorMessage(FString::Printf( TEXT("Failed to wrap '%s': %s."), *(HoudiniAssetActor->GetName()), *WrapperError)); return false; } InWrapper->SetAutoCookingEnabled(bInEnableAutoCook); FDirectoryPath BakeDirectoryPath; BakeDirectoryPath.Path = InBakeDirectoryPath; InWrapper->SetBakeFolder(BakeDirectoryPath); InWrapper->SetBakeMethod(InBakeMethod); InWrapper->SetRemoveOutputAfterBake(bInRemoveOutputAfterBake); InWrapper->SetRecenterBakedActors(bInRecenterBakedActors); InWrapper->SetReplacePreviousBake(bInReplacePreviousBake); InWrapper->SetAutoBakeEnabled(bInEnableAutoBake); return true; } bool UHoudiniPublicAPI::IsAssetCookingPaused_Implementation() const { return FHoudiniEngineCommands::IsAssetCookingPaused(); } void UHoudiniPublicAPI::PauseAssetCooking_Implementation() { if (!IsAssetCookingPaused()) FHoudiniEngineCommands::PauseAssetCooking(); } void UHoudiniPublicAPI::ResumeAssetCooking_Implementation() { if (IsAssetCookingPaused()) FHoudiniEngineCommands::PauseAssetCooking(); } UHoudiniPublicAPIInput* UHoudiniPublicAPI::CreateEmptyInput_Implementation(TSubclassOf InInputClass, UObject* InOuter) { UObject* Outer = InOuter; if (!IsValid(Outer)) Outer = this; UHoudiniPublicAPIInput* const NewInput = NewObject(Outer, InInputClass.Get()); if (!IsValid(NewInput)) { SetErrorMessage(TEXT("Could not create a new valid UHoudiniPublicAPIInput instance.")); } else if (Outer) { // Enable/disable error logging based on the outer's setting (if it is a sub-class of UHoudiniPublicAPIObjectBase) const bool bShouldLogErrors = Outer->IsA() ? Cast(Outer)->IsLoggingErrors() : IsLoggingErrors(); NewInput->SetLoggingErrorsEnabled(bShouldLogErrors); } return NewInput; } EHoudiniPublicAPIRampInterpolationType UHoudiniPublicAPI::ToHoudiniPublicAPIRampInterpolationType(const EHoudiniRampInterpolationType InInterpolationType) { switch (InInterpolationType) { case EHoudiniRampInterpolationType::InValid: return EHoudiniPublicAPIRampInterpolationType::InValid; case EHoudiniRampInterpolationType::BEZIER: return EHoudiniPublicAPIRampInterpolationType::BEZIER; case EHoudiniRampInterpolationType::LINEAR: return EHoudiniPublicAPIRampInterpolationType::LINEAR; case EHoudiniRampInterpolationType::BSPLINE: return EHoudiniPublicAPIRampInterpolationType::BSPLINE; case EHoudiniRampInterpolationType::HERMITE: return EHoudiniPublicAPIRampInterpolationType::HERMITE; case EHoudiniRampInterpolationType::CONSTANT: return EHoudiniPublicAPIRampInterpolationType::CONSTANT; case EHoudiniRampInterpolationType::CATMULL_ROM: return EHoudiniPublicAPIRampInterpolationType::CATMULL_ROM; case EHoudiniRampInterpolationType::MONOTONE_CUBIC: return EHoudiniPublicAPIRampInterpolationType::MONOTONE_CUBIC; } return EHoudiniPublicAPIRampInterpolationType::InValid; } EHoudiniRampInterpolationType UHoudiniPublicAPI::ToHoudiniRampInterpolationType(const EHoudiniPublicAPIRampInterpolationType InInterpolationType) { switch (InInterpolationType) { case EHoudiniPublicAPIRampInterpolationType::InValid: return EHoudiniRampInterpolationType::InValid; case EHoudiniPublicAPIRampInterpolationType::BEZIER: return EHoudiniRampInterpolationType::BEZIER; case EHoudiniPublicAPIRampInterpolationType::LINEAR: return EHoudiniRampInterpolationType::LINEAR; case EHoudiniPublicAPIRampInterpolationType::BSPLINE: return EHoudiniRampInterpolationType::BSPLINE; case EHoudiniPublicAPIRampInterpolationType::HERMITE: return EHoudiniRampInterpolationType::HERMITE; case EHoudiniPublicAPIRampInterpolationType::CONSTANT: return EHoudiniRampInterpolationType::CONSTANT; case EHoudiniPublicAPIRampInterpolationType::CATMULL_ROM: return EHoudiniRampInterpolationType::CATMULL_ROM; case EHoudiniPublicAPIRampInterpolationType::MONOTONE_CUBIC: return EHoudiniRampInterpolationType::MONOTONE_CUBIC; } return EHoudiniRampInterpolationType::InValid; }