GODolphin screenshot 1
B

Publisher

baizeyv

GODolphin

Tools
C# Debug Logging AOP Framework Reactive Modern Singleton

zh-cn: GODOT 的 C# 工具包,包含了从R3仓库中提取的可反应属性的实现,以及从UNITY QFRAMEWORK 中提取的非常好用的工具,并做了一点小小的修改,同时也包含一个现代化外表的 LOG CONSOLE en: GODOT's C# toolkit, including the implementation of reactive properties extracted from the R3 repository, and the very useful tools extracted from UNITY QFRAMEWORK, with a few minor modifications, and also includes a modern-looking LOG CONSOLE

🐬 GODolphin 🐬

Introduce

GODOT's C# toolkit, including the implementation of reactive properties extracted from the R3 repository, and the very useful tools extracted from UNITY QFRAMEWORK, with a few minor modifications, and also includes a modern-looking LOG CONSOLE

AOP Module


Source of demand:

When I am debugging a program, I often need to insert some code before and after a method when calling it somewhere. So I think of AOP, but this function is a bit redundant. After all, I can manually write the code where I want to insert it.

Notice: Only allowed during debugging, otherwise it will cause performance problems

Runtime Example

public override void _Ready()
{
	Proxy
		.Instance.SetTarget(this)
		.SetMethod("TestFOOBAR")
		.SetArguments(new object[] { "HELLO" })
		.SetInvocationHandler(LogInvocationHandler.Instance)
		.Invoke();
}

public void TestFOOBAR(string msg) 
{
	msg += " --WHAT";
	Log.Error().Msg(msg).Do();
}

You Need Create Your Custom InvocationHandler, extend from AbstractInvocationHandler

public class LogInvocationHandler : AbstractInvocationHandler
{
	public static LogInvocationHandler Instance = new LogInvocationHandler();

	private LogInvocationHandler() { }

	public override void Preprocess()
	{
		GD.Print("PRE");
	}

	public override void PostProcess()
	{
		GD.Print("POST");
	}
}

Suggestions:

It is recommended to encapsulate your own static methods directly for easy calling

Log Module


Source of demand:

When I am developing, I need to log in many locations, but their call stacks may be different, so I want to see the call stack of the output. Since the ordinary output of GODOT does not have a call stack, I have this plug-in, and the output of GODOT does not have an accurate time display.

the modern-looking LOG CONSOLE: LogEditorPreview.png

The code in the above picture:

var a = 222;
Log.Debug().Var("a value", a).Sep().Msg("hello").Tag("MYMANAGER").Do();
Log.Warn().Msg("test content hello world").Cr().Msg("????").Do();
Log.Error().Msg("test content hello world").Cr().Msg("????").Do();
Log.Info().Msg("test content hello world").Cr().Msg("????").Do();
Log.Debug().Msg("GOGOGO").Do();
for (var i = 0; i  Normal Info Log
> ```csharp
> Log.Info().Msg("FOO").Cr().Msg("BAR").Do();
> ```

> Debug Variable Log
> ```csharp
> var a = 222;
> Log.Debug().Var("a value", a).Cr().Msg("BAR").Do();
> ```

> Warning Log
> ```csharp
> Log.Warn().Msg("FOO").Sep().Msg("BAR").Do();
> ```

> Error Log
> ```csharp
> Log.Error().Msg("FOO").Sep().Msg("BAR").Do();
> ```

> Line Break API:
>
> ```csharp
> Log.Warn().Cr().Do()
> ``` 
> the `Cr()` is line break

> Dividing Line API:
>
> ```csharp
> Log.Warn().Sep().Do()
> ``` 
> the `Sep()` is dividing line

> Normal Message API:
>
> ```csharp
> Log.Info().Msg("what you say").Do()
> ``` 
> the `Msg()` is normal message

> Specific Variable API:
>
> ```csharp
> Log.Info().Var("your custom variable name", VariableHere).Do()
> ```
> the `Var()` is specific variable

> Tag API:
>
> ```csharp
> Log.Info().Tag("TAG").Msg("HAHA").Do()
> ```
> the `Tag()` is tag 
> 
> (TAG will output at the second, the first is log level, you can call `Tag("")` anywhere, but before `Do()`)

## Resource Module

Resource Editor Preview:

![ResourceEditor.png](https://raw.githubusercontent.com/baizeyv/GODolphin/master/preview%2FResourceEditor.png)

## Singleton Module

Singleton Editor Preview:

![SingletonEditor.png](https://raw.githubusercontent.com/baizeyv/GODolphin/master/preview%2FSingletonEditor.png)

## State Machine Module

State Machine Editor Preview:

![LogEditorPreview.png](https://raw.githubusercontent.com/baizeyv/GODolphin/master/preview%2FStateMachineEditor.png)

Inheritance and chaining can be mixed

Please use this to create new state machine, not `new()`
```csharp
var machine = StateMachineManager.Instance.CreateMachine("LogTypeMachine");

Chaining Example A:

public partial class StateMachineExample1 : Node
{
	public enum States
	{
		A,
		B,
	}

	public StateMachine sm = new();

	public override void _Ready()
	{
		sm.OnStateChanged(
			(prev, now) =>
			{
				GD.Print($"{prev} => {now}");
			}
		);
		sm.State(States.A)
			.OnCondition(() =>
			{
				return sm.CurrentStateId == States.B;
			})
			.OnEnter(() =>
			{
				GD.Print("ENTER A");
			})
			.OnProcess(() =>
			{
				GD.Print("PROCESS A");
			})
			.OnPhysicsProcess(() =>
			{
				GD.Print("PHYSICS PROCESS A");
			})
			.OnExit(() =>
			{
				GD.Print("EXIT A");
			});
		sm.State(States.B)
			.OnCondition(() =>
			{
				return sm.CurrentStateId == States.A;
			});

		sm.StartState(States.A);

		this.AppendAction(
			this.Delay(
				2f,
				this.Callback(() =>
				{
					sm.SwitchState(States.B);
				})
			)
		);
	}

	public override void _Process(double delta)
	{
		sm._Process(delta);
	}

	public override void _PhysicsProcess(double delta)
	{
		sm._PhysicsProcess(delta);
	}

	public override void _ExitTree()
	{
		sm.Clear();
	}
}

Inheritance Example B:

public partial class StateMachineExample2 : Node
{
	public enum States2
	{
		A,
		B,
		C,
	}

	public StateMachine machine = new();

	public class StateA : AbstractState
	{
		public StateA(StateMachine machine, StateMachineExample2 target)
			: base(machine, target) { }

		protected override bool OnCondition()
		{
			return machine.CurrentStateId == States2.B;
		}
	}

	public class StateB : AbstractState
	{
		public StateB(StateMachine machine, StateMachineExample2 target)
			: base(machine, target) { }

		protected override bool OnCondition()
		{
			return machine.CurrentStateId == States2.A;
		}
	}

	public override void _Process(double delta)
	{
		machine._Process(delta);
	}

	public override void _PhysicsProcess(double delta)
	{
		machine._PhysicsProcess(delta);
	}

	public override void _Ready()
	{
		machine.AddState(States2.A, new StateA(machine, this));
		machine.AddState(States2.B, new StateB(machine, this));

		// * 支持和链式模式混用
		machine
			.State(States2.C)
			.OnEnter(() =>
			{
				GD.Print("C Enter");
			});

		machine.StartState(States2.A);
	}

	public override void _ExitTree()
	{
		machine.Clear();
	}
}

UI Module

UI Editor Preview:

UIEditor.png

Press Generate Button Can Generate UI Template Code.

UI Setting Dialog:

UISettingDialog.png

How to install

  • download the .zip and unzip it

  • Move the GODolphin folder into the addons folder of your Godot project, if you don't have this folder you can just create one

  • In Godot, Under Projects -> Projects Settings -> Plugins, Enable the plugin you need whose names contain the GODolphin prefix.