Files
2026-04-18 22:31:51 +02:00

138 lines
4.4 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Aiwaz.Contracts;
using System.Runtime.InteropServices;
using Aiwaz.Core;
namespace Aiwaz.Resources
{
public enum CommandFlags : byte
{
None = 0x00,
SubChainStart = 0x01, // Command will start a new command chain (UseShader for example)
SubChainEnd = 0x02, // Command will end a command chain (Render)
Unique = 0x04, // Similar commands should not be reduced to one Command
StartChain = 0x08, // Command will generate a new command chain
EndChain = 0x10, // Command will end the command chain (RenderGeometry for example)
FlushChain = 0x20, // Command will end the command chain (RenderGeometry for example)
}
public class Command
{
[StructLayout(LayoutKind.Explicit)]
public struct CommandInfoUnion
{
[FieldOffset(0)]
public uint RawValue;
[FieldOffset(0)]
public byte Priority;
[FieldOffset(1)]
public byte SubPriority;
[FieldOffset(2)]
public CommandFlags Flags;
[FieldOffset(3)]
public byte Type;
}
public Command(CommandUser argOwner, CommandFlags argFlags, byte argType)
: this(argOwner, argFlags, argType, 0, 0)
{
}
public Command(CommandUser argOwner, CommandFlags argFlags, byte argType, byte argPriority)
: this(argOwner, argFlags, argType, argPriority, 0)
{
}
public Command(CommandUser argOwner, CommandFlags argFlags, byte argType, byte argPriority, byte argSubPriority)
{
CommandInfo.RawValue = 0;
Owner = argOwner;
Flags = argFlags;
Priority = argPriority;
SubPriority = argSubPriority;
Type = argType;
}
public CommandInfoUnion CommandInfo;
public byte Priority { get { return CommandInfo.Priority; } set { CommandInfo.Priority = value; } }
public byte SubPriority { get { return CommandInfo.SubPriority; } set { CommandInfo.SubPriority = value; } }
public CommandFlags Flags { get { return CommandInfo.Flags; } set { CommandInfo.Flags = value; } }
public byte Type { get { return CommandInfo.Type; } set { CommandInfo.Type = value; } }
public CommandUser Owner;
};
public enum CommandExecuteResult
{
None, // Execution done, proceed to the next Command
RetrySubChain, // Execution should start from a previous "SubChainStart"-flagged Command
RetrySubChainSkipHead // Equal to the above result but skips the as "SubChainStart"-flagged Command
};
public abstract class CommandUser : Resource, IDisposable
{
private List<RenderCommandNode> assignedRenderCommandNodes = new List<RenderCommandNode>();
public List<Command> Commands { get; private set; }
public bool IsPreconditionForNextCommands { get; set; }
public CommandUser()
{
this.Commands = new List<Command>();
Engine.RegisterEngineDisposable(this);
}
~CommandUser()
{
if (!Engine.Initialized)
return;
if (Engine.UnregisterEngineDisposable(this))
this.Dispose();
}
public abstract CommandExecuteResult ExecuteCommand(byte argCommandType, CommandBuffer argCurrentBuffer, int argCurrentPositon);
public void AssignToRenderCommandNode(RenderCommandNode node)
{
assignedRenderCommandNodes.Add(node);
node.MarkDirty();
}
public void UnassignFromRenderCommandNode(RenderCommandNode node)
{
if (assignedRenderCommandNodes.Remove(node))
node.MarkDirty();
}
protected void UnassignFromSceneNodes()
{
for (var i = 0; i < assignedRenderCommandNodes.Count; ++i )
assignedRenderCommandNodes[i].Children.Remove(this);
assignedRenderCommandNodes.Clear();
}
protected void MarkCommandsAsDirty()
{
foreach (var node in assignedRenderCommandNodes)
node.MarkDirty();
}
public new virtual void Dispose()
{
this.WellKnownName = null;
this.UnassignFromSceneNodes();
Engine.UnregisterEngineDisposable(this);
base.Dispose();
}
}
}