{"action":"created","issue":{"url":"https://api.github.com/repos/godotengine/godot/issues/23101","repository_url":"https://api.github.com/repos/godotengine/godot","labels_url":"https://api.github.com/repos/godotengine/godot/issues/23101/labels{/name}","comments_url":"https://api.github.com/repos/godotengine/godot/issues/23101/comments","events_url":"https://api.github.com/repos/godotengine/godot/issues/23101/events","html_url":"https://github.com/godotengine/godot/issues/23101","id":371290542,"node_id":"MDU6SXNzdWUzNzEyOTA1NDI=","number":23101,"title":"Add a GDScript Trait system.","user":{"login":"willnationsdev","id":16217563,"node_id":"MDQ6VXNlcjE2MjE3NTYz","avatar_url":"https://avatars1.githubusercontent.com/u/16217563?v=4","gravatar_id":"","url":"https://api.github.com/users/willnationsdev","html_url":"https://github.com/willnationsdev","followers_url":"https://api.github.com/users/willnationsdev/followers","following_url":"https://api.github.com/users/willnationsdev/following{/other_user}","gists_url":"https://api.github.com/users/willnationsdev/gists{/gist_id}","starred_url":"https://api.github.com/users/willnationsdev/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/willnationsdev/subscriptions","organizations_url":"https://api.github.com/users/willnationsdev/orgs","repos_url":"https://api.github.com/users/willnationsdev/repos","events_url":"https://api.github.com/users/willnationsdev/events{/privacy}","received_events_url":"https://api.github.com/users/willnationsdev/received_events","type":"User","site_admin":false},"labels":[{"id":279097162,"node_id":"MDU6TGFiZWwyNzkwOTcxNjI=","url":"https://api.github.com/repos/godotengine/godot/labels/discussion","name":"discussion","color":"ee77ee","default":false},{"id":73330068,"node_id":"MDU6TGFiZWw3MzMzMDA2OA==","url":"https://api.github.com/repos/godotengine/godot/labels/feature%20proposal","name":"feature proposal","color":"1144ff","default":false},{"id":279098082,"node_id":"MDU6TGFiZWwyNzkwOTgwODI=","url":"https://api.github.com/repos/godotengine/godot/labels/topic:gdscript","name":"topic:gdscript","color":"ffdd44","default":false}],"state":"open","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":25,"created_at":"2018-10-17T22:24:48Z","updated_at":"2018-10-19T19:44:06Z","closed_at":null,"author_association":"CONTRIBUTOR","body":"(Edit:\r\nTo minimize further XY problem issues:\r\nThe problem addressed here is that Godot's Node-Scene system / scripting languages don't yet support creating re-usable, grouped implementations that are 1) specific to the root node's features and 2) that can be swapped around and/or combined. Scripts with static methods or sub-nodes with scripts could be used for the latter bit, and for many cases this works. However, Godot generally prefers you to keep the logic for your scene's overall behavior stored in the root node while it uses data computed by the child nodes or delegates significantly-deviated sub-tasks to them, e.g. a KinematicBody2D doesn't manage animation so it delegates that to an AnimationPlayer.\r\n\r\nHaving a thinner root node that uses \"component\" child nodes to drive its behavior is a weak system in comparison.  Having a largely empty root node that just delegates all of its behavior to child nodes runs counter to this paradigm. The child nodes become behavioral extensions of the root node rather than self-sufficent objects that accomplish a task in their own right. It's very clunky, and the design could be simplified/improved by allowing us to consolidate all of the logic in the root node, but also allow us to break up the logic into different, composable chunks.\r\n\r\nI suppose the topic of this Issue is more about how to deal with the above problem than it is specifically about GDScript, yet I believe GDScript Traits would be the simplest and most straightforward approach to solving the issue.\r\n)\r\n\r\nFor the uninformed, traits are essentially a way of blending two classes together into one (pretty much a copy/paste mechanism), only, rather than literally copy/pasting the text of the files, all you are doing is using a keyword statement to link the two files. (Edit: the trick is that while a script can only inherit one class, it can include multiple traits)\r\n\r\nI'm imagining something where any GDScript file can be used as a trait for another GDScript file, so long as the traited type extends a class inherited by the merged-into script, i.e. a Sprite-extending GDScript can't use a Resource GDScript as a trait, but it can use a Node2D GDScript. I would imagine a syntax similar to this:\r\n\r\n    # move_right_trait.gd\r\n    extends Node2D\r\n    class_name MoveRightTrait # not necessary, but just for clarity\r\n    func move_right():\r\n        position.x += 1\r\n    \r\n    # my_sprite.gd\r\n    extends Sprite\r\n    is MoveRightTrait # maybe add a 'use' or 'trait' keyword for this instead?\r\n    is \"res://move_right_trait.gd\" # alternative if class_name isn't used\r\n    func _physics_process():\r\n        move_right() # MoveRightTrait's content has been merged into this script\r\n        if MoveRightTrait in self:\r\n            print(\"I have a MoveRightTrait\")\r\n\r\nI can see two ways of doing this:\r\n\r\n1. Pre-parse the script via RegEx for \"^trait \\<filepathOrIdentifier\\>\" instances, load the referred to script, get its source code, strip out the header info (tool, extends, class\\_name), insert the text, assign the new source code, and THEN parse the script (this all happens during the script's `reload` process). We'd have to not support trait nesting or continuously re-examine the generated source code after every iteration to see if more trait insertions have been made.\r\n2. Parse the script normally, but teach the parser to recognize the keyword, load the referred to script, *parse* THAT script, and then append its ClassNode's content to the generated ClassNode of the current script (effectively taking the parsed results of one script and adding it to the parsed results of the other script). This would automatically support nesting of traited types.\r\n\r\nOn the other hand, people might *want* the trait GDScript to have a name but might NOT want that GDScript's class\\_name to show up in the CreateDialog (cause it's not meant to be created on its own). In this case, it may actually NOT be a good idea to make *any* script support it; only those that are specially marked (perhaps by writing 'trait' at the top of the file?). Anyway, stuff to think about.\r\n\r\nThoughts?\r\n\r\nEdit: After some pondering, I believe option 2 would be much better since 1) we'd know WHICH script a script segment came from (for better error reporting) and 2) we'd be able to identify errors as they happen since the included scripts must be parsed in sequence, rather than just parsing everything at the end. This would cut down on the processing time it adds to the parsing process."},"comment":{"url":"https://api.github.com/repos/godotengine/godot/issues/comments/431477391","html_url":"https://github.com/godotengine/godot/issues/23101#issuecomment-431477391","issue_url":"https://api.github.com/repos/godotengine/godot/issues/23101","id":431477391,"node_id":"MDEyOklzc3VlQ29tbWVudDQzMTQ3NzM5MQ==","user":{"login":"willnationsdev","id":16217563,"node_id":"MDQ6VXNlcjE2MjE3NTYz","avatar_url":"https://avatars1.githubusercontent.com/u/16217563?v=4","gravatar_id":"","url":"https://api.github.com/users/willnationsdev","html_url":"https://github.com/willnationsdev","followers_url":"https://api.github.com/users/willnationsdev/followers","following_url":"https://api.github.com/users/willnationsdev/following{/other_user}","gists_url":"https://api.github.com/users/willnationsdev/gists{/gist_id}","starred_url":"https://api.github.com/users/willnationsdev/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/willnationsdev/subscriptions","organizations_url":"https://api.github.com/users/willnationsdev/orgs","repos_url":"https://api.github.com/users/willnationsdev/repos","events_url":"https://api.github.com/users/willnationsdev/events{/privacy}","received_events_url":"https://api.github.com/users/willnationsdev/received_events","type":"User","site_admin":false},"created_at":"2018-10-19T19:44:06Z","updated_at":"2018-10-19T19:44:06Z","author_association":"CONTRIBUTOR","body":"@AfterRebelion \r\n\r\n> Take into account, i'm talking about the workflow shown, not the feature used\r\n\r\nIt's ironic that, after you clarify this and I agree with the optimal workflow, and then disagree with later portions of the comment, I then follow it up by basically saying how the \"feature used\" in that video is actually the *ideal* way to tackle this problem in Godot *anyway*. Haha."}}
{"actor":{"display_login":"willnationsdev"}}