// Copyright (c) 2012-2023 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 = IntPtr.Add(memory, _memoryOffset).ToPointer(); var handle = GCHandle.FromIntPtr(Unsafe.Read(ptr)); var state = handle.Target; #if !BUILD_RELEASE if (state == null) throw new NullReferenceException(); #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 = IntPtr.Add(memory, _memoryOffset).ToPointer(); var handle = GCHandle.FromIntPtr(Unsafe.Read(ptr)); handle.Free(); } } }