// Copyright (c) 2012-2024 Wojciech Figat. All rights reserved.
using System;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
#if FLAX_EDITOR
using FlaxEngine.Utilities;
using FlaxEditor.Scripting;
using FlaxEngine.GUI;
#endif
namespace FlaxEngine
{
partial class BehaviorKnowledge
{
///
/// Checks if knowledge has a given goal (exact type match without base class check).
///
/// goal type.
/// True if ahs a given goal, otherwise false.
[Unmanaged]
public bool HasGoal()
{
return HasGoal(typeof(T));
}
///
/// Removes the goal from the knowledge. Does nothing if goal of the given type doesn't exist in the knowledge.
///
/// goal type.
[Unmanaged]
public void RemoveGoal()
{
RemoveGoal(typeof(T));
}
}
partial class BehaviorTreeRootNode
{
#if FLAX_EDITOR
private static bool IsValidBlackboardType(ScriptType type)
{
if (new ScriptType(typeof(SceneObject)).IsAssignableFrom(type))
return false;
if (type.Type != null)
{
if (type.Type.IsDelegate())
return false;
if (typeof(Control).IsAssignableFrom(type.Type))
return false;
if (typeof(Attribute).IsAssignableFrom(type.Type))
return false;
if (type.Type.FullName.StartsWith("FlaxEditor.", StringComparison.Ordinal))
return false;
}
return !type.IsGenericType &&
!type.IsInterface &&
!type.IsStatic &&
!type.IsAbstract &&
!type.IsArray &&
!type.IsVoid &&
(type.IsStructure || ScriptType.FlaxObject.IsAssignableFrom(type)) &&
type.IsPublic &&
type.CanCreateInstance;
}
#endif
}
unsafe partial class BehaviorTreeNode
{
///
/// Gets the size in bytes of the given typed node state structure.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int GetStateSize()
{
// C# nodes state is stored via pinned GCHandle to support holding managed references (eg. string or Vector3[])
return sizeof(IntPtr);
}
///
/// Sets the node state at the given memory address.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void NewState(IntPtr memory, object state)
{
var handle = GCHandle.Alloc(state);
var ptr = IntPtr.Add(memory, _memoryOffset).ToPointer();
Unsafe.Write(ptr, (IntPtr)handle);
}
///
/// Returns the typed node state at the given memory address.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref T GetState(IntPtr memory) where T : struct
{
var ptr = Unsafe.Read(IntPtr.Add(memory, _memoryOffset).ToPointer());
#if !BUILD_RELEASE
if (ptr == IntPtr.Zero)
throw new Exception($"Missing state '{typeof(T).FullName}' for node '{GetType().FullName}'");
#endif
var handle = GCHandle.FromIntPtr(ptr);
var state = handle.Target;
#if !BUILD_RELEASE
if (state == null)
throw new Exception($"Missing state '{typeof(T).FullName}' for node '{GetType().FullName}'");
#endif
return ref Unsafe.Unbox(state);
}
///
/// Frees the allocated node state at the given memory address.
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public void FreeState(IntPtr memory)
{
var ptr = Unsafe.Read(IntPtr.Add(memory, _memoryOffset).ToPointer());
if (ptr == IntPtr.Zero)
return;
var handle = GCHandle.FromIntPtr(ptr);
handle.Free();
}
}
}