FMOD: Cleaning up duplicate platform warning - fmod

FMOD for Unity 2.01.07 (Unity 2019.4.18f1 - running on MacOS Catalina) seems to have broken their FMODStudioSettings class.
I can't save in the editor without getting these errors:
FMOD: Cleaning up duplicate platform: ID = playInEditor, name = 'Play In Editor Settings', type = PlatformPlayInEditor
ArgumentException: An item with the same key has already been added. Key: playInEditor
FMOD: Cleaning up duplicate platform: ID = default, name = 'Default Settings', type = PlatformDefault
ArgumentException: An item with the same key has already been added. Key: default
NullReferenceException: Object reference not set to an instance of an object
FMODUnity.SettingsEditor.DisplayPlugins (System.String title, FMODUnity.Platform platform, FMODUnity.Platform+PropertyAccessor`1[T] property, System.Collections.Generic.Dictionary`2[TKey,TValue] expandState, System.String warning) (at Assets/Plugins/FMOD/src/Editor/SettingsEditor.cs:1028)
I believe this is a regression that basically makes the Unity integration unusable. Something to do with de-duplicating platforms in the Platforms map. At runtime there's a series of NPEs related to platforms so actually I can't run the game properly. Has anyone else run into this?
I'm evaluating FMOD as a middleware option for our game, and have run into at least two serious bugs in the Unity integration. See other bug here.
UPDATE:
I haven't found out why this doesn't happen for everyone, but an easy fix for anyone else running into this issue has been applying this diff:
diff --git a/Assets/Plugins/FMOD/src/Runtime/Settings.cs b/Assets/Plugins/FMOD/src/Runtime/Settings.cs
index 2641e926..c2843145 100644
--- a/Assets/Plugins/FMOD/src/Runtime/Settings.cs
+++ b/Assets/Plugins/FMOD/src/Runtime/Settings.cs
## -817,6 +817,10 ## namespace FMODUnity
private void PopulatePlatformsFromAsset()
{
+ Platforms.Clear();
+ PlatformForBuildTarget.Clear();
+ PlatformForRuntimePlatform.Clear();
+
#if UNITY_EDITOR
string assetPath = AssetDatabase.GetAssetPath(this);
UnityEngine.Object[] assets = AssetDatabase.LoadAllAssetsAtPath(assetPath);
## -827,36 +831,8 ## namespace FMODUnity
foreach (Platform newPlatform in assetPlatforms)
{
- Platform existingPlatform = FindPlatform(newPlatform.Identifier);
-
- if (existingPlatform != null)
- {
- // Duplicate platform; clean one of them up
- Platform platformToDestroy;
-
- if (newPlatform.Active && !existingPlatform.Active)
- {
- Platforms.Remove(existingPlatform.Identifier);
-
- platformToDestroy = existingPlatform;
- existingPlatform = null;
- }
- else
- {
- platformToDestroy = newPlatform;
- }
-
- Debug.LogWarningFormat("FMOD: Cleaning up duplicate platform: ID = {0}, name = '{1}', type = {2}",
- platformToDestroy.Identifier, platformToDestroy.DisplayName, platformToDestroy.GetType().Name);
-
- DestroyImmediate(platformToDestroy, true);
- }
-
- if (existingPlatform == null)
- {
- newPlatform.EnsurePropertiesAreValid();
- Platforms.Add(newPlatform.Identifier, newPlatform);
- }
+ newPlatform.EnsurePropertiesAreValid();
+ Platforms.Add(newPlatform.Identifier, newPlatform);
}
#if UNITY_EDITOR

So this was a bug in the integration they fixed in 2.01.10.

Related

.NET7 Json serialization: cannot handle circular references

I have these tables in my db:
- Turns
- Jobs
- Turns_Jobs (a turn may have multiple jobs, a single job may span across multiple turns)
- Managers (each job has a manager)
These are the corresponding classes:
- Turn
- int TurnID
- ...
- virtual ICollection<Turn_Job> TurnJobs
- Job
- int JobID
- ...
- int ManagerID
- virtual Manager Manager
- ...
- virtual ICollection<Turn_Job> JobTurns
- Turn_Job
- int TurnID
- ...
- virtual Turn Turn
- int JobID
- virtual Job Job
- Manager
- ManagerID
- Name
I'm trying to serialize the following query:
var q = await _db.Turns
.Include(x => x.TurnJobs).ThenInclude(x => x.Job).ThenInclude(x => x.Manager)
.Where(x => true; /* real application has some conditions here */ )
.Select(x => x)
.ToListAsync();
Usually I would do:
var json = JsonSerializer.Serialize(q, new JsonSerializerOptions(JsonSerializerDefaults.Web) { ReferenceHandler = ReferenceHandler.Preserve });
but this throws the following exception:
System.Text.Json.JsonException: The object or value could not be serialized. Path: $.TurnJobs.Job.JobTurns.Turn.TurnJobs.Job.JobTurns.Turn.TurnJobs.Job.JobTurns.Turn.TurnJobs.Job.JobTurns.Turn.TurnJobs.Job.JobTurns.Turn.TurnJobs.Job.JobTurns.Turn.TurnJobs.Job.JobTurns.Turn.TurnJobs.Job.JobTurns.
---> System.InvalidOperationException: CurrentDepth (64) is equal to or larger than the maximum allowed depth of 64. Cannot write the next JSON object or array.
It seems that circular reference is not detected and/or correctly handled.
If I ignore references:
var json = JsonSerializer.Serialize(r, new JsonSerializerOptions(JsonSerializerDefaults.Web) { ReferenceHandler = ReferenceHandler.IgnoreCycles });
the exception becomes:
System.Text.Json.JsonException: A possible object cycle was detected. This can either be due to a cycle or if the object depth is larger than the maximum allowed depth of 64. Consider using ReferenceHandler.Preserve on JsonSerializerOptions to support cycles. Path: $.TurnJobs.Job.JobTurns.Turn.TurnJobs.Job.JobTurns.Turn.TurnJobs.Job.JobTurns.Turn.TurnJobs.Job.JobTurns.Turn.TurnJobs.Job.JobTurns.Turn.TurnJobs.Job.JobTurns.Turn.TurnJobs.Job.JobTurns.Turn.TurnJobs.Job.JobTurns.Turn.TurnJobs.Job.JobTurns.Turn.TurnJobs.Job.JobTurns.Turn.TurnJobs.TurnID.

Unreal Engine 4: What is correct way to PAK files, load/mount them and load assets with AssetRegistry in packaged game?

I want to do this:
Create and package original game. Then I want to create additional PAK files with new meshes/sounds/animations and blueprints based on blueprint in the original game. Original game should not know anything about additional meshes/animations/etc. So I need to create a smart system with AssetRegistry in the original game that scans all PAK files, load/mount them and with AssetRegistry scan those PAK files for all assets.
What I did to achieve my goal:
I create and package successfully original game for the target platform (windows standalone). Then in the project, I create additional content and cook them for the target platform. I use UnrealPak.exe to create PAK files for additional content. I am able to load/mount PAK file in the original game by placing PAK file in Paks folder and they load/mount at startup of the game (this sentence is based on the LOG file from the original game, I don't know how to check if it is true or not). I am able to load/mount PAK file even with code by using FCoreDelegates::OnMountPak.Execute (this sentence is also based on the LOG file from the original game). So loading/mounting PAK files should work well. But now where is the biggest issue. I want to use AssetRegistry to scan for all assets in all PAK files. I tried everything I came up with. I tried ScanPathsSynchronous method, GetAllAssets method. Only what happens is it loads assets from ORIGINAL GAME PAK FILE. It seems that AssetRegistry doesn't know anything about other PAK files. I tried to tell AssetRegistry where are those files with AddPath method and still doesn't work.
So my example code what I tried is here:
FString path1 = FPaths::ConvertRelativePathToFull(FString("../../../TestPaks/Content/Paks/test.pak"));
FString path2 = FPaths::ConvertRelativePathToFull(FString("../../../TestPaks/Content/Paks/testmaterial.pak"));
bool check1 = false;
bool check2 = false;
if (FCoreDelegates::OnMountPak.IsBound())
{
check1 = FCoreDelegates::OnMountPak.Execute(path1, 0, nullptr); //Number should be 0-4; specifies search order
check2 = FCoreDelegates::OnMountPak.Execute(path2, 0, nullptr); //Number should be 0-4; specifies search order
}
UE_LOG(LogTemp, Warning, TEXT("%s"), *path1);
UE_LOG(LogTemp, Warning, TEXT("%s"), *path2);
FString NewString1 = check1 ? "true" : "false";
FString NewString2 = check2 ? "true" : "false";
UE_LOG(LogTemp, Warning, TEXT("check 1 = %s"), *NewString1);
UE_LOG(LogTemp, Warning, TEXT("check 2 = %s"), *NewString2);
FAssetRegistryModule& AssetRegistryModule = FModuleManager::LoadModuleChecked<FAssetRegistryModule>(FName("AssetRegistry"));
IAssetRegistry& assetRegistry = AssetRegistryModule.Get();
TArray<FString> ContentPaths;
TArray<FAssetData> data;
//assetRegistry.AddPath(path1);
FString contentRelativeDir = TEXT("/Game/Paks");
assetRegistry.AddPath(contentRelativeDir);
assetRegistry.ScanPathsSynchronous({ contentRelativeDir });
//assetRegistry.SearchAllAssets(true);
assetRegistry.GetAllAssets(data, false);
assetRegistry.GetAllCachedPaths(ContentPaths);
for (FString& data : ContentPaths)
{
UE_LOG(LogTemp, Warning, TEXT("GetAllCachedPaths: %s"), *data);
}
FString NewString = FString::FromInt(data.Num());
UE_LOG(LogTemp, Warning, TEXT("%s"), *NewString);
for (int32 i = 0; i < data.Num(); i++)
{
FString s = data[i].AssetName.ToString();
FString ss = data[i].AssetClass.ToString();
UE_LOG(LogTemp, Warning, TEXT("%s | %s"), *s, *ss);
}
I tried a lot of versions of paths and nothing is working. I am in this mess around 2 weeks and I don't have any much more tips on what to do and what will work. So how should this work properly??? I looked in forums here and StackOverflow and there are some solutions, but they don't work anymore.
I have loaded asset from .pak file but I use FStreamableManager instead of AssetRegistry.
I will describe what I do...
1) Mount .pak file: I just need to put additional .pak file to WindowNoEditor/[Project_Name]/Content/Paks/ folder (assumed that you package for window), game engine will auto mount that .pak file.
2) Load/Get asset from that .pak file:
FPakPlatformFile *PakPlatformFile;
FString PlatformFileName = FPlatformFileManager::Get().GetPlatformFile().GetName();
if (PlatformFileName.Equals(FString(TEXT("PakFile"))))
{
PakPlatformFile = static_cast<FPakPlatformFile*>(&FPlatformFileManager::Get().GetPlatformFile());
}
else
{
PakPlatformFile = new FPakPlatformFile;
if (!PakPlatformFile->Initialize(&FPlatformFileManager::Get().GetPlatformFile(), TEXT("")))
{
UE_LOG(LogTemp, Error, TEXT("FPakPlatformFile failed to initialize"));
return;
}
FPlatformFileManager::Get().SetPlatformFile(*PakPlatformFile);
}
TArray<FString> ArrAllMountedPakFile;
PakPlatformFile->GetMountedPakFilenames(ArrAllMountedPakFile);
for (int32 i = 0; i < ArrAllMountedPakFile.Num(); i++)
{
FString PakFileName = ArrAllMountedPakFile[i];
FString PakFilePathFull = FPaths::ConvertRelativePathToFull(PakFileName);
FPakFile PakFile(PakPlatformFile, *PakFilePathFull, false);
TArray<FString> FileList;
FString MountPoint = PakFile.GetMountPoint();
PakFile.FindFilesAtPath(FileList, *MountPoint, true, false, true);
for (int32 i = 0; i < FileList.Num(); i++)
{
FString AssetName = FileList[i];
FString AssetShortName = FPackageName::GetShortName(AssetName);
FString FileName, FileExt;
AssetShortName.Split(TEXT("."), &FileName, &FileExt);
FString NewAssetName = TEXT("/Game/<path_to_asset>/") + FileName + TEXT(".") + FileName;
FSoftObjectPath StrNewAssetRef = NewAssetName;
FStreamableManager AssetLoader;
UObject* NewLoadedObject = AssetLoader.LoadSynchronous(StrNewAssetRef);
if (NewLoadedObject)
{
// do something, cast to compatible type.
}
}
}
Hope that to help you. Cheer !

Argument 1 passed to EntityViewBuilder must implement interface, null given

In my Drupal project I have this error:
Recoverable fatal error: Argument 1 passed to
Drupal\Core\Entity\EntityViewBuilder::view() must implement interface
Drupal\Core\Entity\EntityInterface, null given, called in
/Users/team1/workspace/ga_p/modules/field_collection/src/Plugin/Field/FieldFormatter/FieldCollectionItemsFormatter.php
on line 33 and defined in Drupal\Core\Entity\EntityViewBuilder->view()
(line 110 of core/lib/Drupal/Core/Entity/EntityViewBuilder.php). I do
not know if it's from having created multiple fields
(fieldCollections)
But I do not know how to remove this error.
Drupal Version: 8.3.4
Try this patch
diff --git a/src/Plugin/Field/FieldType/FieldCollection.php b/src/Plugin/Field/FieldType/FieldCollection.php
index 8721220..c5335be 100644
--- a/src/Plugin/Field/FieldType/FieldCollection.php
+++ b/src/Plugin/Field/FieldType/FieldCollection.php
## -183,19 +183,15 ## class FieldCollection extends EntityReferenceItem {
public function preSave() {
if ($field_collection_item = $this->getFieldCollectionItem()) {
- // TODO: Handle node cloning
- /*
- if (!empty($host_entity->is_new) && empty($entity->is_new)) {
+ $host = $this->getEntity();
+
+ // Handle node cloning
+ if($host->isNew() && !$field_collection_item->isNew()) {
// If the host entity is new but we have a field_collection that is not
// new, it means that its host is being cloned. Thus we need to clone
// the field collection entity as well.
- $new_entity = clone $entity;
- $new_entity->target_id = NULL;
- $new_entity->revision_id = NULL;
- $new_entity->is_new = TRUE;
- $entity = $new_entity;
+ $field_collection_item = $field_collection_item->createDuplicate();
}
- */
// TODO: Handle deleted items
/*
## -231,11 +227,10 ## class FieldCollection extends EntityReferenceItem {
}
*/
- $this->newHostRevision = $this->getEntity()->isNewRevision();
+ $this->newHostRevision = $host->isNewRevision();
// If the host entity is saved as new revision, do the same for the item.
if ($this->newHostRevision) {
- $host = $this->getEntity();
$field_collection_item->setNewRevision();
diff --git a/src/Plugin/Field/FieldWidget/FieldCollectionEmbedWidget.php b/src/Plugin/Field/FieldWidget/FieldCollectionEmbedWidget.php
index 4d6ae09..800383f 100644
--- a/src/Plugin/Field/FieldWidget/FieldCollectionEmbedWidget.php
+++ b/src/Plugin/Field/FieldWidget/FieldCollectionEmbedWidget.php
## -104,9 +104,8 ## class FieldCollectionEmbedWidget extends WidgetBase {
protected function formMultipleElements(FieldItemListInterface $items, array &$form, FormStateInterface $form_state) {
// We don't want to render empty items on field collection fields
// unless a) the field collection is empty ; b) the form is rebuilding,
- // which means that the user clicked on "Add another item"; or
- // c) we are creating a new entity.
- if ((count($items) > 0) && !$form_state->isRebuilding() && !$items->getEntity()->isNew()) {
+ // which means that the user clicked on "Add another item"
+ if ((count($items) > 0) && !$form_state->isRebuilding()) {
$field_name = $this->fieldDefinition->getName();
$cardinality = $this->fieldDefinition->getFieldStorageDefinition()->getCardinality();
$parents = $form['#parents'];
mentioned here.

llvm Invalid operand for global metadata

I want to assign unique IDs for basic blocks in a module using global metadata. But I got an error: "Invalid operand for global metadata!". Any problems in the follow code snippet?
Here is part of the code I add operand of a named metadata node:
bool runOnModule(Module &M) {
...
NamedMDNode *NMD = M.getOrInsertNamedMetadata(mdKindName);
for (Module::iterator FI = M.begin(), FE = M.end(); FI != FE; ++FI) {
for (Function::iterator BI = FI->begin(), BE = FI->end(); BI != BE; ++BI) {
errs() << "Basic Block number: " << counter << "\n";
NMD->addOperand(assignID(BI, ++counter));
errs() << "Basic Block name: " << BI->getName() << "\n";
}
}
...
}
// Assign unique IDs to Basic Blocks as Metadata Nodes
MDNode* assignID (BasicBlock* BB, unsigned id) {
// Fetch the context in which the enclosing module was defined
LLVMContext &Context = BB->getParent()->getParent()->getContext();
// Create a metadata node that contains ID as a constant:
Value* ID[2];
ID[0] = BB;
ID[1] = ConstantInt::get(Type::getInt32Ty(Context), id);
return MDNode::getWhenValsUnresolved(Context, ArrayRef<Value*>(ID, 2), false);
}
The version of llvm is 3.6.0.
I am using visual studio 2013 for my project.
Thanks,
henry
Solution: ID[0] should store MDString::get(Context, BB->getName())
By passing false as the last argument for getWhenValsUnresolved, you have created a global metadata node. Global metadata may only contain:
Constants, including addresses of global values.
MDNodes.
MDStrings.
If you want to use something which is function-local - such as instruction, argument or (in your case) a basic-block, you need to use local metadata. Create one by using true as the last argument there.

using modernizr and css3pie together in ie8 causes visible css3-container text nodes

it seems if you modify innerhtml of an element, there occurs a race condition that causes rendering of css3-container text node into screen. closest things i could found on the net was this:
https://groups.google.com/forum/#!msg/knockoutjs/M7sZvSFqD5I/Lg9kpNmvkkgJ
http://css3pie.com/forum/viewtopic.php?f=3&t=1531
i had the same problem with fancybox, when i tried to pass html as first parameter.
i tried to solve my problem with this patch to modernizr:
diff --git a/js/libs/modernizr-2.5.3.js b/js/libs/modernizr-2.5.3.js
index c1a6a9a..0bc0d11 100755
--- a/js/libs/modernizr-2.5.3.js
+++ b/js/libs/modernizr-2.5.3.js
## -1071,7 +1071,12 ## window.Modernizr = (function( window, document, undefined ) {
// a 403 response, will cause the tab/window to crash
// * Script elements appended to fragments will execute when their `src`
// or `text` property is set
- var node = (cache[nodeName] || (cache[nodeName] = docCreateElement(nodeName))).cloneNode();
+ var node;
+ if (nodeName == "css3-container") {
+ node = docCreateElement(nodeName);
+ } else {
+ node = (cache[nodeName] || (cache[nodeName] = docCreateElement(nodeName))).cloneNode();
+ }
return html5.shivMethods && node.canHaveChildren && !reSkip.test(nodeName) ? frag.appendChild(node) : node;
};
but it's too hackish, is there any other proper way to get around this problem?
I had the same problem with Modernizr 2.5.3 but upgrading to Modernizr 2.6.1 solved the issue.