Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 18 additions & 1 deletion Source/Editor/Modules/ContentFindingModule.cs
Original file line number Diff line number Diff line change
Expand Up @@ -228,14 +228,24 @@ public List<SearchResult> Search(string charsToFind)
new SearchResult { Name = item.ShortName, Type = assetItem.TypeName, Item = item }
};
}
var actor = FlaxEngine.Object.Find<Actor>(ref id);
var actor = FlaxEngine.Object.Find<Actor>(ref id, true);
if (actor != null)
{
return new List<SearchResult>
{
new SearchResult { Name = actor.Name, Type = actor.TypeName, Item = actor }
};
}
var script = FlaxEngine.Object.Find<Script>(ref id, true);
if (script != null && script.Actor != null)
{
string actorPathStart = $"{script.Actor.Name}/";

return new List<SearchResult>
{
new SearchResult { Name = $"{actorPathStart}{script.TypeName}", Type = script.TypeName, Item = script }
};
}
}
Profiler.BeginEvent("ContentFinding.Search");

Expand Down Expand Up @@ -388,6 +398,13 @@ internal void Open(object o)
Editor.Instance.SceneEditing.Select(actor);
Editor.Instance.Windows.EditWin.Viewport.FocusSelection();
break;
case Script script:
if (script.Actor != null)
{
Editor.Instance.SceneEditing.Select(script.Actor);
Editor.Instance.Windows.EditWin.Viewport.FocusSelection();
}
break;
}
}

Expand Down
42 changes: 42 additions & 0 deletions Source/Engine/Core/Types/LogContexts.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
#include "LogContexts.h"
#include "Engine/Core/Types/Guid.h"
#include "Engine/Core/Types/String.h"

ThreadLocal<LogContextStack> LogContexts::CurrentLogContext;

String LogContextFormatter::Format()
{
LogContextData context = LogContexts::Get();
if (context.ObjectID != Guid::Empty)
return String::Format(TEXT("(Loading source was {0})"), context.ObjectID);

return String("");
}

void LogContexts::Set(const Guid& id)
{
LogContextData context = LogContextData();
context.ObjectID = id;

LogContextStack contextStack = LogContexts::CurrentLogContext.Get();
contextStack.Stack.Push(context);

LogContexts::CurrentLogContext.Set(contextStack);
}

void LogContexts::Clear()
{
LogContextStack contextStack = LogContexts::CurrentLogContext.Get();
contextStack.Stack.Pop();

LogContexts::CurrentLogContext.Set(contextStack);
}

LogContextData LogContexts::Get()
{
LogContextStack contextStack = LogContexts::CurrentLogContext.Get();
if (contextStack.Stack.Count() == 0)
return LogContextData();

return contextStack.Stack.Last();
}
92 changes: 92 additions & 0 deletions Source/Engine/Core/Types/LogContexts.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
#pragma once
#include "Engine/Core/Config.h"
#include "Engine/Scripting/ScriptingType.h"
#include "Engine/Threading/ThreadLocal.h"
#include "Engine/Core/Collections/Array.h"

class String;
struct Guid;

/// <summary>
/// Log context data structure. Contains different kinds of context data for different situtations.
/// </summary>
API_STRUCT() struct FLAXENGINE_API LogContextData
{
DECLARE_SCRIPTING_TYPE_STRUCTURE(LogContextData)

/// <summary>
/// A GUID for an object which this context applies to.
/// </summary>
API_FIELD() Guid ObjectID;
};

template<>
struct TIsPODType<LogContextData>
{
enum { Value = true };
};

/// <summary>
/// Stores a stack of log contexts.
/// </summary>
API_STRUCT() struct FLAXENGINE_API LogContextStack
{
DECLARE_SCRIPTING_TYPE_STRUCTURE(LogContextStack)

/// <summary>
/// Log context stack.
/// </summary>
Array<LogContextData> Stack;
};

template<>
struct TIsPODType<LogContextStack>
{
enum { Value = true };
};

/// <summary>
/// Log context interaction class. Methods are thread local, and as such, the context is as well.
/// This system is used to pass down important information to be logged through large callstacks
/// which don't have any reason to be passing down the information otherwise.
/// </summary>
API_CLASS(Static) class FLAXENGINE_API LogContexts
{
DECLARE_SCRIPTING_TYPE_MINIMAL(LogContexts)

/// <summary>
/// Adds a log context element to the stack to be displayed in warning and error logs.
/// </summary>
/// <param name="id">The GUID of the object this context applies to.</param>
API_FUNCTION() static void Set(const Guid& id);

/// <summary>
/// Pops a log context element off of the stack and discards it.
/// </summary>
API_FUNCTION() static void Clear();

/// <summary>
/// Gets the log context element off the top of stack.
/// </summary>
/// <returns>The log context element at the top of the stack.</returns>
API_FUNCTION() static LogContextData Get();

private:
static ThreadLocal<LogContextStack> CurrentLogContext;
};

/// <summary>
/// Formatting class which will provide a string to apply
/// the current log context to an error or warning.
/// </summary>
API_CLASS(Static) class FLAXENGINE_API LogContextFormatter
{
DECLARE_SCRIPTING_TYPE_MINIMAL(LogContextFormatter)

public:
/// <summary>
/// Returns a string which represents the current log context on the stack.
/// </summary>
/// <returns>The formatted string representing the current log context.</returns>
API_FUNCTION() static String Format();
};
12 changes: 7 additions & 5 deletions Source/Engine/Scripting/Object.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,21 +126,23 @@ public static Object New(Type type)
/// </summary>
/// <param name="id">Unique ID of the object.</param>
/// <typeparam name="T">Type of the object.</typeparam>
/// <param name="skipLog">Whether or not to log warnings when objects aren't found.</param>
/// <returns>Found object or null if missing.</returns>
public static T Find<T>(ref Guid id) where T : Object
public static T Find<T>(ref Guid id, bool skipLog = false) where T : Object
{
return Internal_FindObject(ref id, typeof(T)) as T;
return Internal_FindObject(ref id, typeof(T), skipLog) as T;
}

/// <summary>
/// Finds the object with the given ID. Searches registered scene objects and assets.
/// </summary>
/// <param name="id">Unique ID of the object.</param>
/// <param name="type">Type of the object.</param>
/// <param name="skipLog">Whether or not to log warnings when objects aren't found.</param>
/// <returns>Found object or null if missing.</returns>
public static Object Find(ref Guid id, Type type)
public static Object Find(ref Guid id, Type type, bool skipLog = false)
{
return Internal_FindObject(ref id, type);
return Internal_FindObject(ref id, type, skipLog);
}

/// <summary>
Expand Down Expand Up @@ -335,7 +337,7 @@ public override int GetHashCode()
internal static partial string Internal_GetTypeName(IntPtr obj);

[LibraryImport("FlaxEngine", EntryPoint = "ObjectInternal_FindObject", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(Interop.StringMarshaller))]
internal static partial Object Internal_FindObject(ref Guid id, [MarshalUsing(typeof(Interop.SystemTypeMarshaller))] Type type);
internal static partial Object Internal_FindObject(ref Guid id, [MarshalUsing(typeof(Interop.SystemTypeMarshaller))] Type type, [MarshalAs(UnmanagedType.U1)] bool skipLog = false);

[LibraryImport("FlaxEngine", EntryPoint = "ObjectInternal_TryFindObject", StringMarshalling = StringMarshalling.Custom, StringMarshallingCustomType = typeof(Interop.StringMarshaller))]
internal static partial Object Internal_TryFindObject(ref Guid id, [MarshalUsing(typeof(Interop.SystemTypeMarshaller))] Type type);
Expand Down
6 changes: 6 additions & 0 deletions Source/Engine/Scripting/Script.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include "Script.h"
#include "Engine/Core/Log.h"
#include "Engine/Core/Types/LogContexts.h"
#if USE_EDITOR
#include "Internal/StdTypesContainer.h"
#include "ManagedCLR/MClass.h"
Expand Down Expand Up @@ -330,6 +331,9 @@ void Script::Serialize(SerializeStream& stream, const void* otherObj)

void Script::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
{
// Store Logging Context
LogContexts::Set(GetID());

// Base
SceneObject::Deserialize(stream, modifier);

Expand Down Expand Up @@ -364,4 +368,6 @@ void Script::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier
}
}
}

LogContexts::Clear();
}
5 changes: 3 additions & 2 deletions Source/Engine/Scripting/Scripting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "Engine/Core/ObjectsRemovalService.h"
#include "Engine/Core/Types/TimeSpan.h"
#include "Engine/Core/Types/Stopwatch.h"
#include "Engine/Core/Types/LogContexts.h"
#include "Engine/Content/Asset.h"
#include "Engine/Content/Content.h"
#include "Engine/Engine/EngineService.h"
Expand Down Expand Up @@ -891,7 +892,7 @@ ScriptingObject* Scripting::FindObject(Guid id, MClass* type)
// Check type
if (!type || result->Is(type))
return result;
LOG(Warning, "Found scripting object with ID={0} of type {1} that doesn't match type {2}.", id, String(result->GetType().Fullname), String(type->GetFullName()));
LOG(Warning, "Found scripting object with ID={0} of type {1} that doesn't match type {2}. {3}", id, String(result->GetType().Fullname), String(type->GetFullName()), LogContextFormatter::Format());
return nullptr;
}

Expand All @@ -910,7 +911,7 @@ ScriptingObject* Scripting::FindObject(Guid id, MClass* type)
return asset;
}

LOG(Warning, "Unable to find scripting object with ID={0}. Required type {1}.", id, String(type->GetFullName()));
LOG(Warning, "Unable to find scripting object with ID={0}. Required type {1}. {2}", id, String(type->GetFullName()), LogContextFormatter::Format());
return nullptr;
}

Expand Down
18 changes: 12 additions & 6 deletions Source/Engine/Scripting/ScriptingObject.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "Engine/Level/Actor.h"
#include "Engine/Core/Log.h"
#include "Engine/Core/Types/Pair.h"
#include "Engine/Core/Types/LogContexts.h"
#include "Engine/Utilities/StringConverter.h"
#include "Engine/Content/Asset.h"
#include "Engine/Content/Content.h"
Expand Down Expand Up @@ -708,7 +709,7 @@ DEFINE_INTERNAL_CALL(MString*) ObjectInternal_GetTypeName(ScriptingObject* obj)
return MUtils::ToString(obj->GetType().Fullname);
}

DEFINE_INTERNAL_CALL(MObject*) ObjectInternal_FindObject(Guid* id, MTypeObject* type)
DEFINE_INTERNAL_CALL(MObject*) ObjectInternal_FindObject(Guid* id, MTypeObject* type, bool skipLog = false)
{
if (!id->IsValid())
return nullptr;
Expand All @@ -725,15 +726,20 @@ DEFINE_INTERNAL_CALL(MObject*) ObjectInternal_FindObject(Guid* id, MTypeObject*
{
if (klass && !obj->Is(klass))
{
LOG(Warning, "Found scripting object with ID={0} of type {1} that doesn't match type {2}.", *id, String(obj->GetType().Fullname), String(klass->GetFullName()));
if (!skipLog)
LOG(Warning, "Found scripting object with ID={0} of type {1} that doesn't match type {2}. {3}", *id, String(obj->GetType().Fullname), String(klass->GetFullName()), LogContextFormatter::Format());
return nullptr;
}
return obj->GetOrCreateManagedInstance();
}
if (klass)
LOG(Warning, "Unable to find scripting object with ID={0}. Required type {1}.", *id, String(klass->GetFullName()));
else
LOG(Warning, "Unable to find scripting object with ID={0}", *id);

if (!skipLog)
{
if (klass)
LOG(Warning, "Unable to find scripting object with ID={0}. Required type {1}. {2}", *id, String(klass->GetFullName()), LogContextFormatter::Format());
else
LOG(Warning, "Unable to find scripting object with ID={0}", *id);
}
return nullptr;
}

Expand Down