move standalone projects into own directory
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
Copyright (c) 2021 Valentin Lemière <valentin@ibilon.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,71 @@
|
||||

|
||||
|
||||
[haxe externs](https://github.com/HaxeGodot/godot) | [editor plugin](https://github.com/HaxeGodot/editor-plugin) | [demo](https://github.com/HaxeGodot/squash-the-creeps-3d) | [api doc](https://haxegodot.github.io/godot/) | [discussions](https://github.com/HaxeGodot/godot/discussions)
|
||||
|
||||
# Godot Editor Haxe Support Plugin
|
||||
|
||||
Godot 3.3 engine editor plugin to help with Haxe development.
|
||||
|
||||
The plugin is still in alpha, open an [issue](https://github.com/HaxeGodot/editor-plugin/issues) for bug reports or feature requests.
|
||||
|
||||
## Installation
|
||||
|
||||
The plugin isn't yet available on the godot asset library, to install it you can either:
|
||||
|
||||
* [download this repository](https://github.com/HaxeGodot/editor-plugin/archive/refs/heads/main.zip) and extract it in the `addons/haxe` folder of your project
|
||||
|
||||
You need to remove the `editor-plugin-main` folder added by github: have `addons/haxe/plugin.cfg` not `addons/haxe/editor-plugin-main/plugin.cfg`
|
||||
* add it as a submodule `git submodule add https://github.com/HaxeGodot/editor-plugin.git addons/haxe`
|
||||
|
||||
You need to enable the plugin by going in the Project -> Project Settings menu, Plugins tab, and checking the Enabled box for the Haxe plugin.
|
||||
|
||||
## Setup
|
||||
|
||||
Haxe support requires Godot C#, if it hasn't been setup click on Project -> Tools -> C# -> Create C# solution.
|
||||
|
||||
The plugin can setup by clicking on the Project -> Tools -> Haxe -> Setup menu.
|
||||
|
||||
This will check for the presence of the godot haxelib, update the C# solution and add a hxml.
|
||||
If the project already contains some of these files the setup will be stopped.
|
||||
|
||||
You can also do a [manual setup](#manual-setup) if you want more control.
|
||||
|
||||
## Haxe scripts
|
||||
|
||||
You can add/load/remove a Haxe script on a node by clicking on it, and in the inspector in Node -> Script -> Haxe Script click on the resource box.
|
||||
|
||||
When creating or clicking Edit on an script it'll open in your editor. By default it is configured for VSCode, and can be changed in Project -> Project Settings -> Haxe -> External Editor. For now only `None` and `VSCode` are supported.
|
||||
|
||||
### Building
|
||||
|
||||
You need to build the Haxe code before launching your game, you can do that:
|
||||
|
||||
* by manually using the hxml `haxe build.hxml`
|
||||
* through your editor
|
||||
* directly in the Godot editor in the bottom tab Haxe -> Build Haxe Project
|
||||
|
||||
Note: The files in `scripts/` must all define their main type, for a file `Foo.hx` you must have the type `Foo`, otherwise compilation will fail.
|
||||
|
||||
## Manual setup
|
||||
|
||||
Example hxml:
|
||||
```hxml
|
||||
--cs build
|
||||
--define net-ver=50
|
||||
--define no-compilation
|
||||
--define analyzer-optimize
|
||||
--class-path scripts
|
||||
--library godot
|
||||
--macro godot.Godot.buildProject()
|
||||
--dce full
|
||||
```
|
||||
|
||||
Modify the `<PropertyGroups>` of the `csproj` file:
|
||||
```xml
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<TargetFramework>netstandard2.1</TargetFramework>
|
||||
```
|
||||
|
||||
## License
|
||||
|
||||
The plugin is MIT licensed.
|
||||
@@ -0,0 +1,126 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
enable-background="new 0 0 227.27 227.2705"
|
||||
height="14"
|
||||
viewBox="0 0 14 14.000001"
|
||||
width="14"
|
||||
version="1.1"
|
||||
id="svg30"
|
||||
sodipodi:docname="haxe.svg"
|
||||
inkscape:version="1.0.2 (e86c870879, 2021-01-15)">
|
||||
<metadata
|
||||
id="metadata36">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<defs
|
||||
id="defs34" />
|
||||
<sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
objecttolerance="10"
|
||||
gridtolerance="10"
|
||||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1011"
|
||||
id="namedview32"
|
||||
showgrid="false"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0"
|
||||
inkscape:zoom="25.168247"
|
||||
inkscape:cx="-2.6813108"
|
||||
inkscape:cy="8.1202027"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="g28"
|
||||
inkscape:document-rotation="0" />
|
||||
<g
|
||||
transform="matrix(0.24008588,0,0,0.24008588,-29.864211,-268.49858)"
|
||||
id="g28">
|
||||
<path
|
||||
d="m 153.54527,1125.6329 -16.33394,-1.4926 -12.82162,-5.7964 h 14.57745 l 14.57811,7.2819"
|
||||
fill="#fbc712"
|
||||
id="path2"
|
||||
style="fill:#d6d6d6;fill-opacity:1;stroke-width:0.0813402" />
|
||||
<path
|
||||
d="m 153.54527,1125.6329 17.3111,-2.0052 11.84578,-5.2838 h -14.57926 l -14.57762,7.2819"
|
||||
fill="#fbc712"
|
||||
id="path4"
|
||||
style="fill:#dbdbdb;fill-opacity:1;stroke-width:0.0813402" />
|
||||
<path
|
||||
d="m 153.54527,1169.3679 14.57761,1.7353 14.57927,5.5532 h -14.57926 l -14.57762,-7.2968"
|
||||
fill="#f6871f"
|
||||
id="path6"
|
||||
style="fill:#d6d6d6;fill-opacity:1;stroke-width:0.0813402" />
|
||||
<path
|
||||
d="m 153.54527,1169.3679 -14.57812,1.5669 -14.57745,5.7216 h 14.57745 l 14.57812,-7.2968"
|
||||
fill="#f15e22"
|
||||
id="path8"
|
||||
style="fill:#d1d1d1;fill-opacity:1;stroke-width:0.0813402" />
|
||||
<path
|
||||
d="m 131.67835,1147.5003 -2.15152,17.1164 -5.13712,12.0397 v -14.5774 l 7.28864,-14.587"
|
||||
fill="#fcee23"
|
||||
id="path10"
|
||||
style="fill:#e5e5e5;fill-opacity:1;stroke-width:0.0813402" />
|
||||
<path
|
||||
d="m 131.67835,1147.5003 -1.63904,-15.6753 -5.6496,-13.4811 v 14.578 l 7.28864,14.5701"
|
||||
fill="#fcee23"
|
||||
id="path12"
|
||||
style="fill:#ebebeb;fill-opacity:1;stroke-width:0.0813402" />
|
||||
<path
|
||||
d="m 175.41219,1147.5003 2.10355,-15.8462 5.18526,-13.3102 v 14.578 l -7.28881,14.5701"
|
||||
fill="#f04923"
|
||||
id="path14"
|
||||
style="fill:#c7c7c7;fill-opacity:1;stroke-width:0.0813402" />
|
||||
<path
|
||||
d="m 175.41219,1147.5003 1.422,16.0914 5.86681,13.0647 v -14.5774 l -7.2888,-14.587"
|
||||
fill="#f04923"
|
||||
id="path16"
|
||||
style="fill:#c2c2c2;fill-opacity:1;stroke-width:0.0813402" />
|
||||
<path
|
||||
d="m 124.38971,1118.3439 29.15556,7.289 v 21.8552 h -21.86692 l -7.28864,-29.1293"
|
||||
fill="#f8b218"
|
||||
id="path18"
|
||||
style="fill:#e0e0e0;fill-opacity:1;stroke-width:0.0813402" />
|
||||
<path
|
||||
d="m 124.38971,1176.6564 7.28864,-29.1561 21.86692,-0.012 v 21.8632 l -29.15555,7.2753"
|
||||
fill="#f89d1c"
|
||||
id="path20"
|
||||
style="fill:#dbdbdb;fill-opacity:1;stroke-width:0.0813402" />
|
||||
<path
|
||||
d="m 182.70216,1118.3439 -7.28997,29.1554 -21.86692,-0.011 v -21.8563 l 29.15688,-7.273"
|
||||
fill="#f37321"
|
||||
id="path22"
|
||||
style="fill:#d1d1d1;fill-opacity:1;stroke-width:0.0813402" />
|
||||
<path
|
||||
d="m 182.70216,1176.6564 -29.15689,-7.2885 v -21.8798 l 21.86693,0.012 7.28997,29.1263"
|
||||
fill="#f15e22"
|
||||
id="path24"
|
||||
style="fill:#cccccc;fill-opacity:1;stroke-width:0.0813402" />
|
||||
<path
|
||||
d="m 153.54527,1125.6329 -21.86692,21.8674 21.86692,21.8676 21.86693,-21.8686 -21.86693,-21.8735"
|
||||
fill="#f6871f"
|
||||
id="path26"
|
||||
style="fill:#d6d6d6;fill-opacity:1;stroke-width:0.0813402" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
@@ -0,0 +1,7 @@
|
||||
[plugin]
|
||||
|
||||
name="Haxe"
|
||||
description="Haxe support for the Godot engine."
|
||||
author="ibilon"
|
||||
version="0.1.0"
|
||||
script="scripts/haxe.gd"
|
||||
@@ -0,0 +1,14 @@
|
||||
[gd_scene format=2]
|
||||
|
||||
[node name="About" type="AcceptDialog"]
|
||||
margin_right = 83.0
|
||||
margin_bottom = 58.0
|
||||
window_title = "About Haxe support"
|
||||
dialog_text = "This plugin adds support for the Haxe programming language.
|
||||
Haxe support is in alpha.
|
||||
|
||||
Discuss usage at: https://github.com/HaxeGodot/godot/discussions
|
||||
|
||||
Report bugs about the editor plugin at: https://github.com/HaxeGodot/editor-plugin/issues/
|
||||
Report bugs about the code support at: https://github.com/HaxeGodot/godot/issues/
|
||||
"
|
||||
@@ -0,0 +1,47 @@
|
||||
[gd_scene load_steps=3 format=2]
|
||||
|
||||
[ext_resource path="res://addons/haxe/scripts/building.gd" type="Script" id=1]
|
||||
|
||||
[sub_resource type="StyleBoxFlat" id=1]
|
||||
bg_color = Color( 0.219608, 0.211765, 0.227451, 1 )
|
||||
border_width_left = 3
|
||||
border_width_top = 3
|
||||
border_width_right = 3
|
||||
border_width_bottom = 3
|
||||
border_color = Color( 0.270588, 0.270588, 0.270588, 1 )
|
||||
corner_radius_top_left = 4
|
||||
|
||||
[node name="Control" type="Control"]
|
||||
anchor_left = 0.5
|
||||
anchor_top = 0.5
|
||||
anchor_right = 0.5
|
||||
anchor_bottom = 0.5
|
||||
margin_left = -152.0
|
||||
margin_top = -38.5
|
||||
margin_right = 152.0
|
||||
margin_bottom = 38.5
|
||||
script = ExtResource( 1 )
|
||||
|
||||
[node name="Background" type="Panel" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
custom_styles/panel = SubResource( 1 )
|
||||
|
||||
[node name="Label" type="Label" parent="."]
|
||||
anchor_right = 1.0
|
||||
margin_bottom = 26.0
|
||||
text = "Building Haxe project..."
|
||||
align = 1
|
||||
valign = 1
|
||||
autowrap = true
|
||||
clip_text = true
|
||||
|
||||
[node name="ProgressBar" type="ProgressBar" parent="."]
|
||||
anchor_top = 0.5
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 0.5
|
||||
margin_left = 11.0
|
||||
margin_top = -6.5
|
||||
margin_right = -11.0
|
||||
margin_bottom = 7.5
|
||||
max_value = 1.0
|
||||
@@ -0,0 +1,130 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/haxe/scripts/new_script.gd" type="Script" id=1]
|
||||
|
||||
[node name="NewScript" type="WindowDialog"]
|
||||
margin_right = 350.0
|
||||
margin_bottom = 270.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
window_title = "Attach Node Haxe Script"
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="MarginContainer" type="MarginContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
margin_left = 10.0
|
||||
margin_top = 10.0
|
||||
margin_right = -10.0
|
||||
margin_bottom = -10.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="MarginContainer"]
|
||||
margin_right = 330.0
|
||||
margin_bottom = 250.0
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="GridContainer" type="GridContainer" parent="MarginContainer/VBoxContainer"]
|
||||
margin_right = 330.0
|
||||
margin_bottom = 52.0
|
||||
columns = 2
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="ClassLabel" type="Label" parent="MarginContainer/VBoxContainer/GridContainer"]
|
||||
margin_top = 5.0
|
||||
margin_right = 54.0
|
||||
margin_bottom = 19.0
|
||||
text = "Inherits:"
|
||||
|
||||
[node name="ClassValue" type="LineEdit" parent="MarginContainer/VBoxContainer/GridContainer"]
|
||||
margin_left = 58.0
|
||||
margin_right = 330.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
text = "VBoxContainer"
|
||||
|
||||
[node name="PathLabel" type="Label" parent="MarginContainer/VBoxContainer/GridContainer"]
|
||||
margin_top = 33.0
|
||||
margin_right = 54.0
|
||||
margin_bottom = 47.0
|
||||
text = "Path:"
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Path" type="HBoxContainer" parent="MarginContainer/VBoxContainer/GridContainer"]
|
||||
margin_left = 58.0
|
||||
margin_top = 28.0
|
||||
margin_right = 330.0
|
||||
margin_bottom = 52.0
|
||||
|
||||
[node name="PathValue" type="LineEdit" parent="MarginContainer/VBoxContainer/GridContainer/Path"]
|
||||
margin_right = 256.0
|
||||
margin_bottom = 24.0
|
||||
size_flags_horizontal = 3
|
||||
text = "res://scripts/VBoxContainer.hx"
|
||||
|
||||
[node name="Load" type="Button" parent="MarginContainer/VBoxContainer/GridContainer/Path"]
|
||||
margin_left = 260.0
|
||||
margin_right = 272.0
|
||||
margin_bottom = 24.0
|
||||
|
||||
[node name="PaddingTop" type="Control" parent="MarginContainer/VBoxContainer"]
|
||||
margin_top = 56.0
|
||||
margin_right = 330.0
|
||||
margin_bottom = 66.0
|
||||
rect_min_size = Vector2( 0, 10 )
|
||||
|
||||
[node name="TextEdit" type="RichTextLabel" parent="MarginContainer/VBoxContainer"]
|
||||
margin_top = 70.0
|
||||
margin_right = 330.0
|
||||
margin_bottom = 212.0
|
||||
rect_min_size = Vector2( 0, 110 )
|
||||
size_flags_vertical = 3
|
||||
bbcode_enabled = true
|
||||
scroll_active = false
|
||||
|
||||
[node name="PaddingBottom" type="Control" parent="MarginContainer/VBoxContainer"]
|
||||
margin_top = 216.0
|
||||
margin_right = 330.0
|
||||
margin_bottom = 226.0
|
||||
rect_min_size = Vector2( 0, 10 )
|
||||
|
||||
[node name="Buttons" type="HBoxContainer" parent="MarginContainer/VBoxContainer"]
|
||||
margin_top = 230.0
|
||||
margin_right = 330.0
|
||||
margin_bottom = 250.0
|
||||
alignment = 1
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Left" type="Button" parent="MarginContainer/VBoxContainer/Buttons"]
|
||||
margin_left = 92.0
|
||||
margin_right = 146.0
|
||||
margin_bottom = 20.0
|
||||
text = "Cancel"
|
||||
|
||||
[node name="Padding" type="Control" parent="MarginContainer/VBoxContainer/Buttons"]
|
||||
margin_left = 150.0
|
||||
margin_right = 180.0
|
||||
margin_bottom = 20.0
|
||||
rect_min_size = Vector2( 30, 0 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Right" type="Button" parent="MarginContainer/VBoxContainer/Buttons"]
|
||||
margin_left = 184.0
|
||||
margin_right = 237.0
|
||||
margin_bottom = 20.0
|
||||
text = "Create"
|
||||
@@ -0,0 +1,35 @@
|
||||
[gd_scene load_steps=2 format=2]
|
||||
|
||||
[ext_resource path="res://addons/haxe/scripts/tab.gd" type="Script" id=1]
|
||||
|
||||
[node name="Tab" type="Control"]
|
||||
margin_right = 40.0
|
||||
margin_bottom = 40.0
|
||||
rect_min_size = Vector2( 0, 200 )
|
||||
script = ExtResource( 1 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="VBoxContainer" type="VBoxContainer" parent="."]
|
||||
anchor_right = 1.0
|
||||
anchor_bottom = 1.0
|
||||
rect_min_size = Vector2( 0, 200 )
|
||||
__meta__ = {
|
||||
"_edit_use_anchors_": false
|
||||
}
|
||||
|
||||
[node name="Button" type="Button" parent="VBoxContainer"]
|
||||
margin_right = 130.0
|
||||
margin_bottom = 20.0
|
||||
size_flags_horizontal = 0
|
||||
text = "Build Haxe Project"
|
||||
|
||||
[node name="TextLog" type="TextEdit" parent="VBoxContainer"]
|
||||
margin_top = 24.0
|
||||
margin_right = 130.0
|
||||
margin_bottom = 200.0
|
||||
size_flags_horizontal = 3
|
||||
size_flags_vertical = 3
|
||||
readonly = true
|
||||
context_menu_enabled = false
|
||||
@@ -0,0 +1,182 @@
|
||||
import sys.io.Process;
|
||||
import haxe.xml.Access;
|
||||
import sys.FileSystem;
|
||||
import sys.io.File;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class Setup {
|
||||
public static function main() {
|
||||
// Checking haxelib for godot externs.
|
||||
final haxelibCheck = new Process("haxelib", ["path", "godot"]);
|
||||
if (haxelibCheck.exitCode() != 0) {
|
||||
Sys.print("haxelib");
|
||||
return;
|
||||
}
|
||||
|
||||
// Find unique csproj file.
|
||||
var csproj = null;
|
||||
|
||||
for (entry in FileSystem.readDirectory(".")) {
|
||||
if (FileSystem.isDirectory(entry)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (entry.endsWith(".csproj")) {
|
||||
if (csproj != null) {
|
||||
Sys.print("multiple_csproj");
|
||||
return;
|
||||
}
|
||||
|
||||
csproj = entry;
|
||||
}
|
||||
}
|
||||
|
||||
if (csproj == null) {
|
||||
Sys.print("csproj");
|
||||
return;
|
||||
}
|
||||
|
||||
// Dirty check.
|
||||
final dirty = ["build.hxml", "build/", "scripts/"].filter(entry -> FileSystem.exists(entry));
|
||||
|
||||
if (dirty.length != 0) {
|
||||
Sys.print("dirty:" + dirty.join(" "));
|
||||
return;
|
||||
}
|
||||
|
||||
// Update csproj file.
|
||||
final csprojData = new Access(Xml.parse(File.getContent(csproj)));
|
||||
final propertyGroup = csprojData.node.Project.node.PropertyGroup;
|
||||
|
||||
for (property in propertyGroup.elements) {
|
||||
switch (property.name) {
|
||||
case "AllowUnsafeBlocks", "TargetFramework":
|
||||
propertyGroup.x.removeChild(property.x);
|
||||
|
||||
default:
|
||||
}
|
||||
}
|
||||
|
||||
propertyGroup.x.addChild(Xml.parse("<AllowUnsafeBlocks>true</AllowUnsafeBlocks>"));
|
||||
propertyGroup.x.addChild(Xml.parse("<TargetFramework>netstandard2.1</TargetFramework>"));
|
||||
|
||||
File.saveContent(csproj, XmlPrinter.print(csprojData.x));
|
||||
|
||||
// Create project.
|
||||
FileSystem.createDirectory("scripts");
|
||||
File.saveContent("scripts/import.hx", "import godot.*;\nimport godot.GD.*;\n\nusing godot.Utils;\n");
|
||||
File.saveContent("build.hxml", "--cs build\n--define net-ver=50\n--define no-compilation\n--define analyzer-optimize\n--class-path scripts\n--library godot\n--macro godot.Godot.buildProject()\n--dce full\n");
|
||||
|
||||
final ret = Sys.command("haxe", ["build.hxml"]);
|
||||
if (ret == 0) {
|
||||
Sys.print("ok");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Modified version of haxe.xml.Printer
|
||||
class XmlPrinter {
|
||||
static public function print(xml:Xml) {
|
||||
final printer = new XmlPrinter();
|
||||
printer.writeNode(xml, "");
|
||||
return printer.output.toString();
|
||||
}
|
||||
|
||||
var output:StringBuf;
|
||||
|
||||
function new() {
|
||||
output = new StringBuf();
|
||||
}
|
||||
|
||||
function writeNode(value:Xml, indent:String) {
|
||||
switch (value.nodeType) {
|
||||
case CData:
|
||||
write(indent + "<![CDATA[");
|
||||
write(value.nodeValue);
|
||||
write("]]>");
|
||||
newline();
|
||||
case Comment:
|
||||
var commentContent = value.nodeValue;
|
||||
commentContent = ~/[\n\r\t]+/g.replace(commentContent, "");
|
||||
commentContent = "<!--" + commentContent + "-->";
|
||||
write(indent);
|
||||
write(StringTools.trim(commentContent));
|
||||
newline();
|
||||
case Document:
|
||||
for (child in value) {
|
||||
writeNode(child, indent);
|
||||
}
|
||||
case Element:
|
||||
write(indent + "<");
|
||||
write(value.nodeName);
|
||||
for (attribute in value.attributes()) {
|
||||
write(" " + attribute + "=\"");
|
||||
write(StringTools.htmlEscape(value.get(attribute), true));
|
||||
write("\"");
|
||||
}
|
||||
if (hasChildren(value)) {
|
||||
final textOnly = hasTextOnly(value);
|
||||
write(">");
|
||||
if (!textOnly) {
|
||||
newline();
|
||||
}
|
||||
for (child in value) {
|
||||
writeNode(child, textOnly ? "" : (indent + " "));
|
||||
}
|
||||
write((textOnly ? "" : indent) + "</");
|
||||
write(value.nodeName);
|
||||
write(">");
|
||||
newline();
|
||||
} else {
|
||||
write("/>");
|
||||
newline();
|
||||
}
|
||||
case PCData:
|
||||
final nodeValue = value.nodeValue.trim();
|
||||
if (nodeValue.length != 0) {
|
||||
write(indent + StringTools.htmlEscape(nodeValue));
|
||||
}
|
||||
case ProcessingInstruction:
|
||||
write("<?" + value.nodeValue + "?>");
|
||||
newline();
|
||||
case DocType:
|
||||
write("<!DOCTYPE " + value.nodeValue + ">");
|
||||
newline();
|
||||
}
|
||||
}
|
||||
|
||||
inline function write(input:String) {
|
||||
output.add(input);
|
||||
}
|
||||
|
||||
inline function newline() {
|
||||
output.add("\n");
|
||||
}
|
||||
|
||||
function hasTextOnly(value:Xml):Bool {
|
||||
for (child in value) {
|
||||
switch (child.nodeType) {
|
||||
case PCData:
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function hasChildren(value:Xml):Bool {
|
||||
for (child in value) {
|
||||
switch (child.nodeType) {
|
||||
case Element, PCData:
|
||||
return true;
|
||||
case CData, Comment:
|
||||
if (StringTools.ltrim(child.nodeValue).length != 0) {
|
||||
return true;
|
||||
}
|
||||
case _:
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
tool
|
||||
class_name Building
|
||||
|
||||
extends Control
|
||||
|
||||
func build_haxe_project():
|
||||
print("Building haxe project...");
|
||||
|
||||
var res = OS.execute("haxe", ["build.hxml"], true);
|
||||
|
||||
$ProgressBar.value = 1
|
||||
yield(VisualServer, 'frame_post_draw')
|
||||
|
||||
print("Project builded with code: ", res)
|
||||
|
||||
queue_free()
|
||||
@@ -0,0 +1,6 @@
|
||||
tool
|
||||
class_name HaxePluginConstants
|
||||
|
||||
const SETTING_HIDE_NATIVE_SCRIPT_FIELD := "haxe/hide_native_script_field"
|
||||
const SETTING_EXTERNAL_EDITOR := "haxe/external_editor"
|
||||
const BUILD_ON_PLAY := "haxe/build_on_play"
|
||||
@@ -0,0 +1,164 @@
|
||||
tool
|
||||
class_name HaxePluginEditorProperty
|
||||
extends EditorProperty
|
||||
|
||||
var haxe_icon := preload("res://addons/haxe/icons/haxe.svg")
|
||||
var new_script_dialog := preload("res://addons/haxe/scenes/new_script.tscn")
|
||||
|
||||
var base:Control
|
||||
var object:Node
|
||||
var script_name := ""
|
||||
var script_path := ""
|
||||
var b:MenuButton
|
||||
var b2:MenuButton
|
||||
|
||||
func setup(base:Control, object:Node) -> void:
|
||||
self.base = base
|
||||
self.object = object
|
||||
label = "Haxe Script"
|
||||
|
||||
var h := HBoxContainer.new()
|
||||
|
||||
# TODO revert icon
|
||||
b = MenuButton.new()
|
||||
b.flat = true
|
||||
h.add_child(b)
|
||||
|
||||
b2 = MenuButton.new()
|
||||
b2.flat = true
|
||||
b2.icon = base.get_icon("GuiDropdown", "EditorIcons")
|
||||
h.add_child(b2)
|
||||
|
||||
add_child(h)
|
||||
|
||||
update_property()
|
||||
|
||||
func setup_menu(base:Control, button:MenuButton, has_script:bool) -> void:
|
||||
if not button.is_connected("gui_input", self, "on_menu_gui"):
|
||||
button.connect("gui_input", self, "on_menu_gui")
|
||||
|
||||
var menu := button.get_popup()
|
||||
|
||||
for i in range(menu.get_item_count()):
|
||||
menu.remove_item(0)
|
||||
|
||||
if not has_script:
|
||||
menu.add_icon_item(base.get_icon("ScriptCreate", "EditorIcons"), "New Haxe Script")
|
||||
else:
|
||||
menu.add_icon_item(base.get_icon("ScriptRemove", "EditorIcons"), "Remove Haxe Script")
|
||||
|
||||
menu.add_icon_item(base.get_icon("Load", "EditorIcons"), "Load Haxe Script")
|
||||
|
||||
if has_script:
|
||||
menu.add_icon_item(base.get_icon("Edit", "EditorIcons"), "Edit")
|
||||
|
||||
if not menu.is_connected("index_pressed", self, "on_popup_select"):
|
||||
menu.connect("index_pressed", self, "on_popup_select", [has_script])
|
||||
|
||||
func on_menu_gui(event:InputEvent) -> void:
|
||||
# If is right click then pretend it's a left click
|
||||
if event is InputEventMouseButton and event.pressed and event.button_index == 2:
|
||||
event.button_index = 1
|
||||
|
||||
func on_popup_select(id:int, has_script:bool) -> void:
|
||||
if id == 0: # New/Remove
|
||||
if not has_script: # New
|
||||
var dialog := new_script_dialog.instance()
|
||||
dialog.setup(base, object.get_class(), object.get_path().get_name(object.get_path().get_name_count() - 1))
|
||||
dialog.theme = base.theme
|
||||
dialog.connect("create", self, "on_create")
|
||||
base.add_child(dialog)
|
||||
dialog.popup_centered()
|
||||
else: # Remove
|
||||
object.remove_meta("haxe_script")
|
||||
object.set_script(null)
|
||||
elif id == 1: # Load
|
||||
var dialog := EditorFileDialog.new()
|
||||
base.add_child(dialog)
|
||||
dialog.access = EditorFileDialog.ACCESS_RESOURCES
|
||||
dialog.current_dir = "res://scripts/"
|
||||
dialog.mode = EditorFileDialog.MODE_OPEN_FILE
|
||||
dialog.theme = base.theme
|
||||
dialog.add_filter("*.hx ; Haxe script")
|
||||
dialog.connect("file_selected", self, "on_load_file")
|
||||
dialog.popup_centered_ratio()
|
||||
elif id == 2: # Edit
|
||||
open_file(script_path)
|
||||
else:
|
||||
print("Unknown entry: ", id)
|
||||
|
||||
func on_create(is_load:bool, class_value:String, path_value:String) -> void:
|
||||
if not is_load:
|
||||
var f := path_value.find_last("/")
|
||||
var name := path_value.substr(f + 1, path_value.find_last(".hx") - f - 1)
|
||||
|
||||
var d := path_value.substr(14).split("/")
|
||||
d.remove(d.size() - 1)
|
||||
|
||||
var pack := d.join(".")
|
||||
if not pack.empty():
|
||||
pack = " " + pack;
|
||||
|
||||
if class_value == name:
|
||||
class_value = "godot." + class_value
|
||||
|
||||
var file := File.new()
|
||||
file.open(path_value, File.WRITE)
|
||||
file.store_string("package" + pack + ";\n\nclass " + name + " extends " + class_value + " {\n}\n")
|
||||
file.close()
|
||||
|
||||
open_file(path_value)
|
||||
|
||||
on_load_file(path_value)
|
||||
|
||||
func open_file(path:String) -> void:
|
||||
var editor:String = ProjectSettings.get(HaxePluginConstants.SETTING_EXTERNAL_EDITOR)
|
||||
if editor == "None":
|
||||
pass
|
||||
elif editor == "VSCode":
|
||||
OS.execute("code", [ProjectSettings.globalize_path(path)], false)
|
||||
else:
|
||||
print("Unknown external editor: " + editor)
|
||||
|
||||
func on_load_file(path:String) -> void:
|
||||
object.set_meta("haxe_script", path)
|
||||
var cs_path := path.replace("res://scripts", "")
|
||||
var p := cs_path.find_last("/")
|
||||
var name := cs_path.substr(p, cs_path.length() - 2 - p) + "cs"
|
||||
cs_path = "build/src" + cs_path.substr(0, p)
|
||||
|
||||
var d := Directory.new()
|
||||
d.make_dir_recursive(cs_path)
|
||||
|
||||
var file_path := "res://" + cs_path + name
|
||||
var cs_file := File.new()
|
||||
if not cs_file.file_exists(file_path):
|
||||
cs_file.open(file_path, File.WRITE)
|
||||
cs_file.store_string("\n")
|
||||
cs_file.close()
|
||||
object.set_script(load(file_path))
|
||||
|
||||
func update_property() -> void:
|
||||
var script_name := "[empty]"
|
||||
|
||||
if object.has_meta("haxe_script"):
|
||||
if not object.get_script():
|
||||
object.remove_meta("haxe_script")
|
||||
else:
|
||||
script_path = object.get_meta("haxe_script")
|
||||
var p := script_path.find_last("/")
|
||||
script_name = script_path.substr(p + 1)
|
||||
|
||||
var has_script := script_path != ""
|
||||
|
||||
b.size_flags_horizontal = MenuButton.SIZE_EXPAND_FILL
|
||||
if has_script:
|
||||
b.icon = haxe_icon
|
||||
b.text = script_name
|
||||
b.hint_tooltip = script_path
|
||||
setup_menu(base, b, has_script)
|
||||
|
||||
setup_menu(base, b2, has_script)
|
||||
|
||||
func get_tooltip_text() -> String:
|
||||
return "Haxe Script"
|
||||
@@ -0,0 +1,103 @@
|
||||
tool
|
||||
class_name HaxePlugin
|
||||
extends EditorPlugin
|
||||
|
||||
var about_dialog := preload("res://addons/haxe/scenes/about.tscn")
|
||||
var tab := preload("res://addons/haxe/scenes/tab.tscn").instance()
|
||||
var build_dialog := preload("res://addons/haxe/scenes/building.tscn")
|
||||
|
||||
var inspector_plugin:HaxePluginInspectorPlugin
|
||||
|
||||
func _enter_tree() -> void:
|
||||
var base := get_editor_interface().get_base_control()
|
||||
|
||||
# Init
|
||||
setup_settings()
|
||||
|
||||
# Inspector plugin
|
||||
inspector_plugin = HaxePluginInspectorPlugin.new()
|
||||
inspector_plugin.setup(base)
|
||||
add_inspector_plugin(inspector_plugin)
|
||||
|
||||
# Tool menu entry
|
||||
var menu := PopupMenu.new()
|
||||
menu.add_item("About")
|
||||
menu.add_item("Setup")
|
||||
menu.connect("index_pressed", self, "on_menu")
|
||||
add_tool_submenu_item("Haxe", menu)
|
||||
|
||||
# Bottom dock tab
|
||||
tab.setup(base)
|
||||
add_control_to_bottom_panel(tab, "Haxe")
|
||||
|
||||
func _exit_tree() -> void:
|
||||
# TODO tab.gd still leaks?
|
||||
remove_control_from_bottom_panel(tab)
|
||||
tab.queue_free()
|
||||
remove_tool_menu_item("Haxe")
|
||||
remove_inspector_plugin(inspector_plugin)
|
||||
|
||||
func setup_settings() -> void:
|
||||
if not ProjectSettings.has_setting(HaxePluginConstants.SETTING_HIDE_NATIVE_SCRIPT_FIELD):
|
||||
ProjectSettings.set_setting(HaxePluginConstants.SETTING_HIDE_NATIVE_SCRIPT_FIELD, true)
|
||||
|
||||
if not ProjectSettings.has_setting(HaxePluginConstants.SETTING_EXTERNAL_EDITOR):
|
||||
ProjectSettings.set_setting(HaxePluginConstants.SETTING_EXTERNAL_EDITOR, "VSCode")
|
||||
ProjectSettings.add_property_info({
|
||||
"name": HaxePluginConstants.SETTING_EXTERNAL_EDITOR,
|
||||
"type": TYPE_STRING,
|
||||
"hint": PROPERTY_HINT_ENUM,
|
||||
"hint_string": "None,VSCode"
|
||||
});
|
||||
|
||||
if not ProjectSettings.has_setting(HaxePluginConstants.BUILD_ON_PLAY):
|
||||
ProjectSettings.set_setting(HaxePluginConstants.BUILD_ON_PLAY, false)
|
||||
|
||||
func on_menu(id:int) -> void:
|
||||
var theme := get_editor_interface().get_base_control().theme
|
||||
|
||||
if id == 0: # About
|
||||
var dialog := about_dialog.instance()
|
||||
add_child(dialog)
|
||||
dialog.theme = theme
|
||||
dialog.popup_centered()
|
||||
elif id == 1: # Setup
|
||||
var output := []
|
||||
OS.execute("haxe", ["--class-path", "addons/haxe/scripts", "--run", "Setup"], true, output, true)
|
||||
|
||||
var dialog := AcceptDialog.new()
|
||||
add_child(dialog)
|
||||
|
||||
if output.size() != 1:
|
||||
dialog.dialog_text = "Unknown error:\n" + PoolStringArray(output).join("\n")
|
||||
elif "command not found" in output[0].to_lower():
|
||||
dialog.dialog_text = "Haxe command not found."
|
||||
elif output[0] == "haxelib":
|
||||
dialog.dialog_text = "Godot externs not found.\nRun 'haxelib install godot' first."
|
||||
elif output[0] == "multiple_csproj":
|
||||
dialog.dialog_text = "Multiple C# solutions found.\nCannot setup."
|
||||
elif output[0] == "csproj":
|
||||
dialog.dialog_text = "C# solution not found (.csproj file).\nYou need to setup Godot Mono first:\nProject -> Tools -> Mono -> Create C# solution."
|
||||
elif output[0].begins_with("dirty:"):
|
||||
dialog.dialog_text = "Project already contains: " + output[0].substr(6) + "\nTo avoid data loss the setup wasn't run."
|
||||
elif output[0] == "ok":
|
||||
dialog.dialog_text = "Setup successful."
|
||||
else:
|
||||
dialog.dialog_text = "Unknown error: " + output[0]
|
||||
|
||||
dialog.theme = theme
|
||||
dialog.window_title = "Haxe Setup"
|
||||
dialog.popup_centered()
|
||||
else:
|
||||
print("Unknown menu: ", id)
|
||||
|
||||
func _input(event):
|
||||
if event is InputEventKey and ProjectSettings.get_setting(HaxePluginConstants.BUILD_ON_PLAY):
|
||||
if event.scancode == KEY_F5 or event.scancode == KEY_F6 and event.echo:
|
||||
var dialog = build_dialog.instance()
|
||||
|
||||
add_child(dialog)
|
||||
|
||||
yield(VisualServer, 'frame_post_draw')
|
||||
|
||||
dialog.call("build_haxe_project")
|
||||
@@ -0,0 +1,22 @@
|
||||
tool
|
||||
class_name HaxePluginInspectorPlugin
|
||||
extends EditorInspectorPlugin
|
||||
|
||||
var base:Control
|
||||
|
||||
func setup(base:Control) -> void:
|
||||
self.base = base
|
||||
|
||||
#warning-ignore:unused_argument
|
||||
func can_handle(object:Object) -> bool:
|
||||
return true
|
||||
|
||||
#warning-ignore:unused_argument
|
||||
func parse_property(object:Object, type:int, path:String, hint:int, hint_text:String, usage:int) -> bool:
|
||||
if object is Node and type == TYPE_OBJECT and path == "script":
|
||||
var e := HaxePluginEditorProperty.new()
|
||||
e.setup(base, object)
|
||||
add_custom_control(e)
|
||||
return ProjectSettings.get_setting(HaxePluginConstants.SETTING_HIDE_NATIVE_SCRIPT_FIELD)
|
||||
|
||||
return false
|
||||
@@ -0,0 +1,157 @@
|
||||
tool
|
||||
extends WindowDialog
|
||||
|
||||
signal create(is_load, class_value, path_value)
|
||||
|
||||
var base:Control
|
||||
|
||||
var cancel_button:Button
|
||||
var create_button:Button
|
||||
|
||||
var class_valid := true
|
||||
var path_valid := true
|
||||
var name_valid := true
|
||||
var name_warning := false
|
||||
var extension_valid := true
|
||||
|
||||
var is_load := false
|
||||
var class_value := ""
|
||||
var path_value := ""
|
||||
|
||||
func setup(base:Control, class_value:String, name:String) -> void:
|
||||
self.base = base
|
||||
|
||||
var left := $MarginContainer/VBoxContainer/Buttons/Left
|
||||
var right := $MarginContainer/VBoxContainer/Buttons/Right
|
||||
|
||||
if OS.get_name() == "Windows" or OS.get_name() == "UWP":
|
||||
setup_buttons(right, left)
|
||||
else:
|
||||
setup_buttons(left, right)
|
||||
|
||||
$MarginContainer/VBoxContainer/GridContainer/ClassValue.connect("text_changed", self, "on_class")
|
||||
$MarginContainer/VBoxContainer/GridContainer/Path/PathValue.connect("text_changed", self, "on_path")
|
||||
|
||||
var path_button := $MarginContainer/VBoxContainer/GridContainer/Path/Load
|
||||
path_button.icon = base.get_icon("Folder", "EditorIcons")
|
||||
path_button.connect("button_down", self, "on_folder")
|
||||
|
||||
on_class(class_value)
|
||||
on_path("res://scripts/" + name.substr(0, 1).to_upper() + name.substr(1) + ".hx")
|
||||
|
||||
func setup_buttons(cancel:Button, create:Button) -> void:
|
||||
cancel.text = "Cancel"
|
||||
cancel.connect("button_down", self, "on_cancel")
|
||||
cancel_button = cancel
|
||||
|
||||
create.text = "Create"
|
||||
create.connect("button_down", self, "on_create")
|
||||
create_button = create
|
||||
|
||||
func on_cancel() -> void:
|
||||
hide()
|
||||
|
||||
func on_create() -> void:
|
||||
hide()
|
||||
emit_signal("create", is_load, class_value, path_value)
|
||||
|
||||
func on_class(value:String) -> void:
|
||||
class_value = value
|
||||
class_valid = ClassDB.class_exists(value) and ClassDB.can_instance(value)
|
||||
revalidate()
|
||||
|
||||
func on_folder() -> void:
|
||||
var file := path_value
|
||||
file = file.substr(file.find_last("/") + 1)
|
||||
|
||||
var dialog := EditorFileDialog.new()
|
||||
base.add_child(dialog)
|
||||
dialog.access = EditorFileDialog.ACCESS_RESOURCES
|
||||
dialog.current_dir = "res://scripts/"
|
||||
dialog.current_file = file
|
||||
dialog.disable_overwrite_warning = true
|
||||
dialog.theme = base.theme
|
||||
dialog.window_title = "Open Haxe Script / Choose Location"
|
||||
dialog.add_filter("*.hx ; Haxe script")
|
||||
dialog.connect("file_selected", self, "on_path")
|
||||
dialog.get_ok().text = "Open"
|
||||
dialog.popup_centered_ratio()
|
||||
|
||||
func on_path(fullpath:String) -> void:
|
||||
path_value = fullpath
|
||||
|
||||
var dir_p := fullpath.find_last("/")
|
||||
var ext_p := fullpath.find_last(".")
|
||||
|
||||
var path := ""
|
||||
var file := ""
|
||||
|
||||
if dir_p < ext_p:
|
||||
path = fullpath.substr(0, dir_p)
|
||||
file = fullpath.substr(dir_p + 1)
|
||||
else:
|
||||
path = fullpath
|
||||
|
||||
var d := Directory.new()
|
||||
var f := File.new()
|
||||
|
||||
is_load = f.file_exists(path_value)
|
||||
extension_valid = file.ends_with(".hx")
|
||||
name_valid = ext_p < fullpath.length() - 1 and ext_p > dir_p + 1
|
||||
name_warning = name_valid && extension_valid && isBuiltin(file.substr(0, file.length() - 3))
|
||||
path_valid = path.begins_with("res://") and d.dir_exists(path)
|
||||
revalidate()
|
||||
|
||||
func isBuiltin(name:String) -> bool:
|
||||
var haxeGodotBuiltins = ["Action", "CustomSignal", "CustomSignalUsings", "Godot", "Nullable1", "Signal", "SignalUsings", "Utils"]
|
||||
return ClassDB.class_exists(name) or haxeGodotBuiltins.has(name)
|
||||
|
||||
func revalidate() -> void:
|
||||
var text_edit := $MarginContainer/VBoxContainer/TextEdit
|
||||
text_edit.bbcode_text = ""
|
||||
|
||||
var valid_color := Color(0.062775, 0.730469, 0.062775)
|
||||
var error_color := Color(0.820312, 0.028839, 0.028839)
|
||||
var warning_color := Color(0.9375, 0.537443, 0.06958)
|
||||
|
||||
if not class_valid:
|
||||
text_edit.push_color(error_color)
|
||||
text_edit.append_bbcode("- Invalid inherited parent name.\n\n")
|
||||
text_edit.pop()
|
||||
elif not extension_valid:
|
||||
text_edit.push_color(error_color)
|
||||
text_edit.append_bbcode("- Invalid extension.\n\n")
|
||||
text_edit.pop()
|
||||
elif not path_valid:
|
||||
text_edit.push_color(error_color)
|
||||
text_edit.append_bbcode("- Invalid path.\n\n")
|
||||
text_edit.pop()
|
||||
elif not name_valid:
|
||||
text_edit.push_color(error_color)
|
||||
text_edit.append_bbcode("- Invalid filename.\n\n")
|
||||
text_edit.pop()
|
||||
else:
|
||||
text_edit.push_color(valid_color)
|
||||
text_edit.append_bbcode("- Haxe script path is valid.\n\n")
|
||||
|
||||
if is_load:
|
||||
text_edit.append_bbcode("- Will load an existing Haxe script.\n\n")
|
||||
else:
|
||||
text_edit.append_bbcode("- Will create a new Haxe script.\n\n")
|
||||
|
||||
text_edit.pop()
|
||||
|
||||
if name_warning:
|
||||
text_edit.push_color(warning_color)
|
||||
text_edit.append_bbcode("Warning: Having the script name be the same as a built-in type is usually not desired.\n\n")
|
||||
text_edit.pop()
|
||||
|
||||
var class_edit:LineEdit = $MarginContainer/VBoxContainer/GridContainer/ClassValue
|
||||
var class_edit_column := class_edit.caret_position
|
||||
class_edit.text = class_value
|
||||
class_edit.caret_position = class_edit_column if class_edit_column <= class_value.length() else class_value.length()
|
||||
|
||||
var path_edit:LineEdit = $MarginContainer/VBoxContainer/GridContainer/Path/PathValue
|
||||
var path_edit_column := path_edit.caret_position
|
||||
path_edit.text = path_value
|
||||
path_edit.caret_position = path_edit_column if path_edit_column <= path_value.length() else path_value.length()
|
||||
@@ -0,0 +1,67 @@
|
||||
tool
|
||||
extends Control
|
||||
|
||||
onready var button := $VBoxContainer/Button
|
||||
onready var text_log := $VBoxContainer/TextLog
|
||||
|
||||
var base:Control
|
||||
var icon := 0
|
||||
var icons := []
|
||||
var mutex := Mutex.new()
|
||||
var output := []
|
||||
var time := 0.0
|
||||
var thread:Thread = null
|
||||
|
||||
func setup(base:Control) -> void:
|
||||
self.base = base
|
||||
|
||||
for i in range(8):
|
||||
icons.append(base.get_icon("Progress%s"%(i + 1), "EditorIcons"))
|
||||
|
||||
func _ready() -> void:
|
||||
button.connect("button_down", self, "build_haxe_project")
|
||||
|
||||
func build_haxe_project() -> void:
|
||||
if thread != null:
|
||||
return
|
||||
|
||||
thread = Thread.new()
|
||||
|
||||
button.icon = icons[0]
|
||||
button.text = "Building Haxe Project ..."
|
||||
icon = 0
|
||||
text_log.text = ""
|
||||
time = 0.0
|
||||
output = []
|
||||
|
||||
thread.start(self, "run_thread")
|
||||
|
||||
func _process(delta:float) -> void:
|
||||
if thread != null:
|
||||
update_log()
|
||||
time += delta
|
||||
if time > 0.1:
|
||||
time = 0
|
||||
icon = (icon + 1) % 8
|
||||
button.icon = icons[icon]
|
||||
|
||||
func run_thread(userdata) -> void:
|
||||
var ret := OS.execute("haxe", ["build.hxml"], true, output, true)
|
||||
update_log()
|
||||
button.icon = base.get_icon("StatusSuccess" if ret == 0 else "StatusError", "EditorIcons")
|
||||
button.text = "Build Haxe Project"
|
||||
call_deferred("end_thread")
|
||||
|
||||
func end_thread() -> void:
|
||||
thread.wait_to_finish()
|
||||
thread = null
|
||||
|
||||
func update_log() -> void:
|
||||
mutex.lock()
|
||||
text_log.text = PoolStringArray(output).join("\n")
|
||||
mutex.unlock()
|
||||
|
||||
func _exit_tree():
|
||||
if thread != null:
|
||||
thread.wait_to_finish()
|
||||
thread = null
|
||||
Reference in New Issue
Block a user