Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support writing editor plugin in C# #15237

Closed
mysticfall opened this issue Jan 1, 2018 · 16 comments
Closed

Support writing editor plugin in C# #15237

mysticfall opened this issue Jan 1, 2018 · 16 comments

Comments

@mysticfall
Copy link
Contributor

mysticfall commented Jan 1, 2018

Godot version:

Built from f11a138 with PR #15136.

OS/device including version:

Majaro Linux 17.1-rc2

Issue description:

First of all, excuse me if the issue looks more like a question. I don't understand Godot enough to narrow down the problem further, so please feel free to edit the issue as you see fit.

What I want to achieve is to create a library type editor addon in C# and use it from another project. Let's say, I created relevant projects as follows:

  • myproject-logging (The editor plugin project)
    /project.godot
    /plugin.cfg
    /Logging Project.sln
    /Logging Project.csproj
    /namespace/LoggingPlugin.cs (extends EditorPlugin and has [Tool] attribute.)

  • myproject-game (The actual game project)
    /addons/myproject-logging (Symbolic link to myproject-logging)
    /project.godot
    /Game Project.sln
    /Game Project.csproj (Contains a reference to the dll assembly of myproject-logging)

I managed to build both of the projects successfully, and also confirmed that myproject-game can reference and invoke API from myproject-logging in Godot editor.

But when I tried to load myproject-logging as a plugin, it failed. I tried to track down the problem further and found following information:

  • EditorNode::set_addon_plugin_enabled fails to get the proper base type for the C# 'script' specified in plugin.cfg(returns '').
  • CSharpScript::get_instance_base_type() seems to resolve the given class name in myproject-game's assembly, rather than that of myproject-logging.
  • The resolving process seems to rely on parsing the file name to infer the class name, ignoring namespace information.

It is problematic because it means in order to make an editor plugin which is written in C# to work, relevant source files need to be included in the assembly of the referring project.

And because it does not take into account a namespace, there's potential issue of conflicting names between classes.

Ideally, classes defined by a C# plugin can be referenced by another project using their fully qualified names and used in their binary forms.

I have limited knowledge of C#, C++, and Godot, so there's a chance that some of the above problems could be from my misunderstanding of how it works.

In that case, please let me know, so I could update the issue accordingly or close it.

Thanks!

@willnationsdev
Copy link
Contributor

willnationsdev commented Jan 1, 2018

I think part of the problem here (which I didn't realize you were doing before) is that you have multiple nested .godot project files that are relying on each other. As far as I know, that isn't doable.

For my own plugin, I had to have one project with my add-on code inside of a demo project (for development and testing), and then I had a separate repository that is JUST the addon folder with a license and readme file (to be included into other projects). The Asset Library just directly inserts the content into your res:// folder, so the addon doesn't work if it also includes a project.

Idk if that will fix the issue, but it's worth a shot. Can probably just remove the Godot project file in the logging directory to test it.

@mysticfall
Copy link
Contributor Author

mysticfall commented Jan 1, 2018

@willnationsdev Thanks for the suggestion. I just tested again with just plugin.cfg and relevant source files but the result didn't change.

By the way, I think we probably need to distribute an assembly(*.dll) of the plugin as well in case it's also meant to be used as a library too.

In my particular example, the logging library depends on various external references like Microsoft.Extensions.Logging, NETStandard.Library, Ensure.That, and so on. And it did work correctly if the library was referenced by the main project in its binary form, except for the plugin part.

If I just distribute the source files and plugin.cfg, users would need to find out what external references and build settings the library was originally built with and add them to their own project manually, which I suppose would make it more of a code snippet than an actual library.

Rather, I wish I could just make a plugin with dll assemblies without any source files. If Godot could support specifying a fully qualified class name (i.e. myproject.logging.LoggingPlugin) in script field of plugin.cfg, and maybe automatically update *.csproject file for the main project to add such assemblies from the added plugin as references.

At least, I suppose we need some guideline or convention where to put the plugin assemblies even if they are not used by the plugin system for now.

@mhilbrunner
Copy link
Member

Tool mode / plugins are plainly not supported yet for C#, I think. CC @neikeq

@willnationsdev
Copy link
Contributor

Ohhhhhh, that would explain it.

@mysticfall
Copy link
Contributor Author

In that case, I'll patiently wait for the official release of 3.0 😄

But probably, it might be worth while to discuss about potential issues of plugin support for C# here, especially about how resolving of class names should work in that context.

@paulloz
Copy link
Member

paulloz commented Feb 25, 2018

Is there anything I can work on that would make C# addons a bit more possible?

@mysticfall
Copy link
Contributor Author

@paulloz I believe #7402 could be a prerequisite of this issue, so I'd much appreciate if you (or anyone who's capable) could see what can be done with it.

@neikeq
Copy link
Contributor

neikeq commented Mar 10, 2018

I can't read the entire issue right now, but I want to clear a confusion. #17409 is not one of the problems/causes.

I still didn't think in detail how plugins should work.
One way is to add all the C# sources in the plugin to the main C# project, but I don't like this for various obvious reasons.
A different solution would be that each plugin has its own project that is added as a ProjectReference to the main project. This would require Godot to be able to find node derived classes in different assemblies, not only the right now known as project_assembly; and other changes to the editor related to this.

@neikeq neikeq added this to the 3.1 milestone Mar 10, 2018
@mysticfall
Copy link
Contributor Author

mysticfall commented Mar 10, 2018

I definitely agree that adding all the sources to the main project is not the way to go. Unity takes this approach, and it's error prone and makes the project cluttered with all sorts of warnings from 3rd party assets. And I also believe it would involve some complexity in implementation too (i.e. auto detecting managed assemblies, changnig of source files, two-way synchronization of *.csproj and more.)

So, I agree that it'd be best to let each addon to provide it's own assembly. I initially thought we'd eventually support distributing and reusing addons in their binary assembly form, but it seems like it's far from having a concensus, so I'll be happy with having ProjectReference (instead of just Reference) as long as it fixes this problem.

@neikeq
Copy link
Contributor

neikeq commented Mar 10, 2018

I don't see why we cannot support pre-built assemblies as well :)

@mysticfall
Copy link
Contributor Author

mysticfall commented Mar 10, 2018

Of course, assemblies work great already :) It's just that it's not possible to assign them to nodes and I still feel uneasy about having two separate ways of distributing addons.

@twilson90
Copy link

twilson90 commented May 21, 2018

Is there any likelihood of this issue being resolved?
It would be great to write EditorPlugins or EditorScripts in C#

@neikeq
Copy link
Contributor

neikeq commented Nov 30, 2018

I just created #24091 which improves tool scripts support quite a bit. As explained in there, the workflow for editor plugins is pretty bad right now but they should be more or less working.

I think we should close this issue and open a new one for every specific problem found with tool scripts or editor plugins in C# (this includes any discussion about how the workflow should be).

@akien-mga
Copy link
Member

Closing as fixed by #24091, albeit with the caveats mentioned there and in the above comment.

@scott-lin
Copy link

Is there documentation on how to write a tool using C#? This GitHub issue is closed here, but I can't find documentation for it. I was looking at https://docs.godotengine.org/en/3.1/tutorials/misc/running_code_in_the_editor.html

@scott-lin
Copy link

Looks like the docs just haven't been updated yet, but I figured it out. Will note down for others if they come across this. Simply add [Tool] attribute to your class.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants