AkSSlider.cpp 9.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. /*******************************************************************************
  2. The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
  3. Technology released in source code form as part of the game integration package.
  4. The content of this file may not be used without valid licenses to the
  5. AUDIOKINETIC Wwise Technology.
  6. Note that the use of the game engine is subject to the Unreal(R) Engine End User
  7. License Agreement at https://www.unrealengine.com/en-US/eula/unreal
  8. License Usage
  9. Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
  10. this file in accordance with the end user license agreement provided with the
  11. software or, alternatively, in accordance with the terms contained
  12. in a written agreement between you and Audiokinetic Inc.
  13. Copyright (c) 2023 Audiokinetic Inc.
  14. *******************************************************************************/
  15. #include "AkWaapiSlate/Widgets/Input/AkSSlider.h"
  16. #include "AkAudioDevice.h"
  17. #include "Widgets/SBoxPanel.h"
  18. #include "Widgets/Input/SSlider.h"
  19. #include "Widgets/Text/STextBlock.h"
  20. #include "WaapiPicker/SWaapiPicker.h"
  21. #include "AkWaapiUMG/Components/WwiseUmgDragDropOp.h"
  22. #include "AkWaapiUMG/Components/WwisePropertyDragDropOp.h"
  23. #include "AkWaapiUtils.h"
  24. #include "Widgets/Input/SNumericEntryBox.h"
  25. /*------------------------------------------------------------------------------------
  26. Defines
  27. ------------------------------------------------------------------------------------*/
  28. #define LOCTEXT_NAMESPACE "AkWaapiUMG"
  29. /*------------------------------------------------------------------------------------
  30. Helpers
  31. ------------------------------------------------------------------------------------*/
  32. /*------------------------------------------------------------------------------------
  33. Implementation
  34. ------------------------------------------------------------------------------------*/
  35. void AkSSlider::Construct(const AkSSlider::FArguments& InDeclaration)
  36. {
  37. check(InDeclaration._Style);
  38. OnDropDelegate = InDeclaration._OnDrop;
  39. this->ChildSlot
  40. [
  41. SNew(SVerticalBox)
  42. + SVerticalBox::Slot()
  43. .AutoHeight()
  44. .HAlign(HAlign_Center)
  45. .VAlign(VAlign_Center)
  46. [
  47. SNew(SVerticalBox)
  48. + SVerticalBox::Slot()
  49. .AutoHeight()
  50. .HAlign(HAlign_Center)
  51. .VAlign(VAlign_Center)
  52. [
  53. SNew(STextBlock)
  54. .Text(this, &AkSSlider::GetAkSliderItemControlled)
  55. ]
  56. + SVerticalBox::Slot()
  57. .AutoHeight()
  58. .HAlign(HAlign_Center)
  59. .VAlign(VAlign_Center)
  60. [
  61. SNew(STextBlock)
  62. .Text(this, &AkSSlider::GetAkSliderProperty)
  63. ]
  64. + SVerticalBox::Slot()
  65. .AutoHeight()
  66. .HAlign(HAlign_Center)
  67. .VAlign(VAlign_Center)
  68. [
  69. SNew(SNumericEntryBox<double>)
  70. .Value(this, &AkSSlider::GetAkSliderValue)
  71. .MinValue(this, &AkSSlider::GetAkSliderRangeMin)
  72. .MinSliderValue(this, &AkSSlider::GetAkSliderRangeMin)
  73. .MaxValue(this, &AkSSlider::GetAkSliderRangeMax)
  74. .MaxSliderValue(this, &AkSSlider::GetAkSliderRangeMax)
  75. .OnValueCommitted(this, &AkSSlider::OnValueCommitted)
  76. ]
  77. ]
  78. + SVerticalBox::Slot()
  79. [
  80. SAssignNew(AkScrubberSSlider, SSlider)
  81. .OnValueChanged(this, &AkSSlider::HandleAkSliderValueChanged)
  82. .Style(InDeclaration._Style)
  83. ]
  84. ];
  85. }
  86. TSharedPtr<SSlider> AkSSlider::GetAkSilder() const
  87. {
  88. return AkScrubberSSlider;
  89. }
  90. TOptional<double> AkSSlider::GetAkSliderValue() const
  91. {
  92. if (AkScrubberSSlider.IsValid())
  93. return AkScrubberSSlider->GetValue()*(UIMaxValue - UIMinValue) + UIMinValue;
  94. return 0.0f;
  95. }
  96. FText AkSSlider::GetAkSliderProperty() const
  97. {
  98. return FText::FromString(TEXT("Property : ") + AkSliderItemProperty);
  99. }
  100. FText AkSSlider::GetAkSliderItemControlled() const
  101. {
  102. return FText::FromString(TEXT("Item : ") + ItemControlled);
  103. }
  104. void AkSSlider::HandleAkSliderValueChanged(float NewValue)
  105. {
  106. if (AkSliderItemId.IsEmpty() || AkSliderItemProperty.IsEmpty())
  107. {
  108. UE_LOG(LogAkAudio, Log, TEXT("No item or property to control"));
  109. return;
  110. }
  111. // Construct the arguments Json object"
  112. TSharedRef<FJsonObject> args = MakeShareable(new FJsonObject());
  113. {
  114. args->SetStringField(WwiseWaapiHelper::OBJECT, AkSliderItemId);
  115. args->SetStringField(WwiseWaapiHelper::PROPERTY, AkSliderItemProperty);
  116. args->SetNumberField(WwiseWaapiHelper::VALUE, NewValue*(UIMaxValue - UIMinValue) + UIMinValue); // e.i. This gives us a range of volume from [-96 to 12] for the volume property
  117. }
  118. // Construct the options Json object;
  119. TSharedRef<FJsonObject> options = MakeShareable(new FJsonObject());
  120. // Connect to Wwise Authoring on localhost.
  121. FAkWaapiClient* waapiClient = FAkWaapiClient::Get();
  122. if (waapiClient == nullptr)
  123. {
  124. return;
  125. }
  126. #if AK_SUPPORT_WAAPI
  127. TSharedPtr<FJsonObject> outJsonResult;
  128. // Request data from Wwise using WAAPI
  129. if (!waapiClient->Call(ak::wwise::core::object::setProperty, args, options, outJsonResult))
  130. {
  131. UE_LOG(LogAkAudio, Log, TEXT("Failed to set property %s on AKSSlider"), *AkSliderItemProperty);
  132. }
  133. #endif
  134. }
  135. FReply AkSSlider::OnDrop(const FGeometry& MyGeometry, const FDragDropEvent& DragDropEvent)
  136. {
  137. FReply HandledState = FReply::Unhandled();
  138. TSharedPtr<FDragDropOperation> Operation = DragDropEvent.GetOperation();
  139. if (Operation.IsValid())
  140. {
  141. if (Operation->IsOfType<FWwiseUmgDragDropOp>())
  142. {
  143. const auto& AssetDragDropOp = StaticCastSharedPtr<FWwiseUmgDragDropOp>(Operation);
  144. if (AssetDragDropOp.IsValid())
  145. {
  146. const auto& WwiseAssets = AssetDragDropOp->GetWiseItems();
  147. if (WwiseAssets.Num() && WwiseAssets[0].IsValid())
  148. {
  149. SetAkSliderItemId(WwiseAssets[0]->ItemId.ToString(EGuidFormats::DigitsWithHyphensInBraces));
  150. }
  151. if (OnDropDelegate.IsBound())
  152. {
  153. HandledState = OnDropDelegate.Execute(MyGeometry, DragDropEvent);
  154. }
  155. if (!HandledState.IsEventHandled())
  156. {
  157. if (WwiseAssets.Num() && WwiseAssets[0].IsValid())
  158. {
  159. HandledState = FReply::Handled();
  160. }
  161. }
  162. }
  163. }
  164. else if (Operation->IsOfType<FWwisePropertyDragDropOp>())
  165. {
  166. const auto& AssetDragDropOp = StaticCastSharedPtr<FWwisePropertyDragDropOp>(Operation);
  167. if (AssetDragDropOp.IsValid())
  168. {
  169. const auto& WwiseAssets = AssetDragDropOp->GetWiseProperties();
  170. if (WwiseAssets.Num() && WwiseAssets[0].IsValid())
  171. {
  172. SetAkSliderItemProperty(*WwiseAssets[0].Get());
  173. }
  174. if (OnDropDelegate.IsBound())
  175. {
  176. HandledState = OnDropDelegate.Execute(MyGeometry, DragDropEvent);
  177. }
  178. if (!HandledState.IsEventHandled())
  179. {
  180. if (WwiseAssets.Num() && WwiseAssets[0].IsValid())
  181. {
  182. HandledState = FReply::Handled();
  183. }
  184. }
  185. }
  186. }
  187. }
  188. return HandledState;
  189. }
  190. void AkSSlider::SetAkSliderItemProperty(const FString& ItemProperty)
  191. {
  192. if (!ItemProperty.IsEmpty() && (AkSliderItemProperty != ItemProperty))
  193. {
  194. AkSliderItemProperty = ItemProperty;
  195. UpdateRange();
  196. }
  197. }
  198. const FString& AkSSlider::GetAkSliderItemProperty() const
  199. {
  200. return AkSliderItemProperty;
  201. }
  202. void AkSSlider::SetAkSliderItemId(const FString& ItemId)
  203. {
  204. if (!ItemId.IsEmpty() && (AkSliderItemId != ItemId))
  205. {
  206. AkSliderItemId = ItemId;
  207. TSharedPtr<FJsonObject> getResult;
  208. FString itemName = TEXT("");
  209. if (SWaapiPicker::CallWaapiGetInfoFrom(WwiseWaapiHelper::ID, AkSliderItemId, getResult, {}))
  210. {
  211. // Recover the information from the Json object getResult and use it to get the item name.
  212. TArray<TSharedPtr<FJsonValue>> StructJsonArray = getResult->GetArrayField(WwiseWaapiHelper::RETURN);
  213. if (StructJsonArray.Num() > 0)
  214. {
  215. const TSharedPtr<FJsonObject>& ItemInfoObj = StructJsonArray[0]->AsObject();
  216. ItemControlled = ItemInfoObj->GetStringField(WwiseWaapiHelper::NAME);
  217. }
  218. }
  219. UpdateRange();
  220. }
  221. }
  222. inline void AkSSlider::UpdateRange()
  223. {
  224. if(AkSliderItemId.IsEmpty())
  225. return;
  226. // Construct the arguments Json object.
  227. TSharedRef<FJsonObject> args = MakeShareable(new FJsonObject());
  228. args->SetStringField(WwiseWaapiHelper::OBJECT, AkSliderItemId);
  229. args->SetStringField(WwiseWaapiHelper::PROPERTY, AkSliderItemProperty);
  230. // Construct the options Json object.
  231. TSharedRef<FJsonObject> options = MakeShareable(new FJsonObject());
  232. TSharedPtr<FJsonObject> outJsonResult;
  233. // Connect to Wwise Authoring on localhost.
  234. FAkWaapiClient* waapiClient = FAkWaapiClient::Get();
  235. if (waapiClient)
  236. {
  237. #if AK_SUPPORT_WAAPI
  238. // Request data from Wwise using WAAPI
  239. if (waapiClient->Call(ak::wwise::core::object::getPropertyInfo, args, options, outJsonResult))
  240. {
  241. // Recover the information from the Json object outJsonResult and use it to get the property state.
  242. if (outJsonResult->HasField(WwiseWaapiHelper::UI))
  243. {
  244. TSharedPtr<FJsonObject> uiLimit = outJsonResult->GetObjectField(WwiseWaapiHelper::UI)->GetObjectField(WwiseWaapiHelper::VALUE);
  245. UIMinValue = uiLimit->GetNumberField(WwiseWaapiHelper::MIN);
  246. UIMaxValue = uiLimit->GetNumberField(WwiseWaapiHelper::MAX);
  247. }
  248. }
  249. #endif
  250. }
  251. }
  252. const FString& AkSSlider::GetAkSliderItemId() const
  253. {
  254. return AkSliderItemId;
  255. }
  256. void AkSSlider::SetAkSliderRangeMax(const double in_NewValue)
  257. {
  258. UIMaxValue = in_NewValue;
  259. }
  260. void AkSSlider::SetAkSliderRangeMin(const double in_NewValue)
  261. {
  262. UIMinValue = in_NewValue;
  263. }
  264. TOptional<double> AkSSlider::GetAkSliderRangeMin() const
  265. {
  266. return UIMinValue;
  267. }
  268. TOptional<double> AkSSlider::GetAkSliderRangeMax() const
  269. {
  270. return UIMaxValue;
  271. }
  272. void AkSSlider::OnValueCommitted(double InNewValue, ETextCommit::Type Commit)
  273. {
  274. if (AkSliderItemProperty.IsEmpty() || InNewValue > UIMaxValue || InNewValue < UIMinValue)
  275. {
  276. return;
  277. }
  278. const float newValue = (InNewValue - UIMinValue) / (UIMaxValue - UIMinValue);
  279. if (AkScrubberSSlider.IsValid())
  280. AkScrubberSSlider->SetValue(newValue);
  281. HandleAkSliderValueChanged(newValue);
  282. }
  283. #undef LOCTEXT_NAMESPACE