Skip to content

Commit

Permalink
Start setting up godot-zig.
Browse files Browse the repository at this point in the history
  • Loading branch information
Makosai committed Aug 18, 2024
1 parent dc2d86e commit 3e46f21
Show file tree
Hide file tree
Showing 11 changed files with 495 additions and 7 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,15 @@
export.cfg
# export_presets.cfg

# Godot Zig
./godot/lib/
**/.godot/**
**/*.import
*code-workspace

!**/.godot/extension_list.cfg
!**/.godot/global_script_class_cache.cfg

# Imported translations (automatically generated from CSV files)
*.translation

Expand Down
7 changes: 0 additions & 7 deletions rust/README.md

This file was deleted.

33 changes: 33 additions & 0 deletions zig/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# This file is for zig-specific build artifacts.
# If you have OS-specific or editor-specific files to ignore,
# such as *.swp or .DS_Store, put those in your global
# ~/.gitignore and put this in your ~/.gitconfig:
#
# [core]
# excludesfile = ~/.gitignore
#
# Cheers!
# -andrewrk

.zig-cache/
zig-out/
/release/
/debug/
/build/
/build-*/
/docgen_tmp/

# Although this was renamed to .zig-cache, let's leave it here for a few
# releases to make it less annoying to work with multiple branches.
zig-cache/


.vscode
.DS_Store
gen
**/.godot/**
**/*.import
*code-workspace

!**/.godot/extension_list.cfg
!**/.godot/global_script_class_cache.cfg
3 changes: 3 additions & 0 deletions zig/.gitmodules
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[submodule "godot-zig"]
path = godot-zig
url = https://github.com/godot-zig/godot-zig
7 changes: 7 additions & 0 deletions zig/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# Reia
## This section utilizes godot-zig to take advantage of Ziig.

Use cases:
- Custom NetCode
- PostgreSQL for authentication
- Turso/LibSQL for online / offline database
36 changes: 36 additions & 0 deletions zig/build.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
const std = @import("std");

pub fn build(b: *std.Build) !void {
const target = b.standardTargetOptions(.{});
const optimize = b.standardOptimizeOption(.{});
const godot_path = b.option([]const u8, "godot", "Path to Godot engine binary [default: `godot`]") orelse "godot";

const lib = b.addSharedLibrary(.{
.name = "reia",
.root_source_file = .{ .path = "src/Reia.zig" },
.target = target,
.optimize = optimize,
});

const godot_zig_build = @import("./godot-zig/build.zig");
const godot = godot_zig_build.createModule(b, target, optimize, godot_path);
lib.root_module.addImport("godot", godot);

// use explicit imports to make jump work properly
// todo: remove this once zls get improved
var iter = godot.import_table.iterator();
while (iter.next()) |it| {
lib.root_module.addImport(it.key_ptr.*, it.value_ptr.*);
}
/////////////////////////////////////////////////

b.lib_dir = "../godot/lib";
b.installArtifact(lib);

const run_cmd = b.addSystemCommand(&.{
godot_path, "--path", "../godot",
});
run_cmd.step.dependOn(b.getInstallStep());
const run_step = b.step("run", "Run with Godot");
run_step.dependOn(&run_cmd.step);
}
172 changes: 172 additions & 0 deletions zig/src/ExampleNode.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,172 @@
const std = @import("std");
const Godot = @import("godot");
const Vec2 = Godot.Vector2;
const Vec3 = Godot.Vector3;
const SpritesNode = @import("SpriteNode.zig");
const GuiNode = @import("GuiNode.zig");
const SignalNode = @import("SignalNode.zig");
const Examples = [_]struct { name: [:0]const u8, T: type }{
.{ .name = "Sprites", .T = SpritesNode },
.{ .name = "GUI", .T = GuiNode },
.{ .name = "Signals", .T = SignalNode },
};

const Self = @This();
pub usingnamespace Godot.Node;
base: Godot.Node,

panel: Godot.PanelContainer,
example_node: ?Godot.Node = null,

property1: Vec3,
property2: Vec3,

const property1_name: [:0]const u8 = "Property1";
const property2_name: [:0]const u8 = "Property2";

pub fn init(self: *Self) void {
std.log.info("init {s}", .{@typeName(@TypeOf(self))});
}

pub fn deinit(self: *Self) void {
std.log.info("deinit {s}", .{@typeName(@TypeOf(self))});
}

fn clear_scene(self: *Self) void {
if (self.example_node) |n| {
Godot.destroy(n);
//n.queue_free(); //ok
}
}

pub fn on_timeout(_: *Self) void {
std.debug.print("on_timeout\n", .{});
}

pub fn on_resized(_: *Self) void {
std.debug.print("on_resized\n", .{});
}

pub fn on_item_focused(self: *Self, idx: i64) void {
self.clear_scene();
switch (idx) {
inline 0...Examples.len - 1 => |i| {
const n = Godot.create(Examples[i].T) catch unreachable;
self.example_node = Godot.cast(Godot.Node, n.base);
self.panel.add_child(self.example_node, false, Godot.Node.INTERNAL_MODE_DISABLED);
self.panel.grab_focus();
},
else => {},
}
}

pub fn _enter_tree(self: *Self) void {
inline for (Examples) |E| {
Godot.registerClass(E.T);
}

//initialize fields
self.example_node = null;
self.property1 = Vec3.new(111, 111, 111);
self.property2 = Vec3.new(222, 222, 222);

if (Godot.Engine.getSingleton().is_editor_hint()) return;

const window_size = self.get_tree().?.get_root().?.get_size();
var sp = Godot.initHSplitContainer();
sp.set_h_size_flags(Godot.Control.SIZE_EXPAND_FILL);
sp.set_v_size_flags(Godot.Control.SIZE_EXPAND_FILL);
sp.set_split_offset(@intFromFloat(@as(f32, @floatFromInt(window_size.x)) * 0.2));
sp.set_anchors_preset(Godot.Control.PRESET_FULL_RECT, false);
var itemList = Godot.initItemList();
inline for (0..Examples.len) |i| {
_ = itemList.add_item(Examples[i].name, null, true);
}
var timer = self.get_tree().?.create_timer(1.0, true, false, false);
defer _ = timer.?.unreference();

Godot.connect(timer.?, "timeout", self, "on_timeout");
Godot.connect(sp, "resized", self, "on_resized");

Godot.connect(itemList, "item_selected", self, "on_item_focused");
self.panel = Godot.initPanelContainer();
self.panel.set_h_size_flags(Godot.Control.SIZE_FILL);
self.panel.set_v_size_flags(Godot.Control.SIZE_FILL);
self.panel.set_focus_mode(Godot.Control.FOCUS_ALL);
sp.add_child(itemList, false, Godot.Node.INTERNAL_MODE_DISABLED);
sp.add_child(self.panel, false, Godot.Node.INTERNAL_MODE_DISABLED);
self.base.add_child(sp, false, Godot.Node.INTERNAL_MODE_DISABLED);
}

pub fn _exit_tree(self: *Self) void {
_ = self;
}

pub fn _notification(self: *Self, what: i32) void {
if (what == Godot.Node.NOTIFICATION_WM_CLOSE_REQUEST) {
if (!Godot.Engine.getSingleton().is_editor_hint()) {
self.get_tree().?.quit(0);
}
}
}

pub fn _get_property_list(_: *Self) []const Godot.PropertyInfo {
const C = struct {
var properties: [32]Godot.PropertyInfo = undefined;
};

C.properties[0] = Godot.PropertyInfo.init(Godot.GDEXTENSION_VARIANT_TYPE_VECTOR3, Godot.StringName.initFromLatin1Chars(property1_name));
C.properties[1] = Godot.PropertyInfo.init(Godot.GDEXTENSION_VARIANT_TYPE_VECTOR3, Godot.StringName.initFromLatin1Chars(property2_name));

return C.properties[0..2];
}

pub fn _property_can_revert(_: *Self, name: Godot.StringName) bool {
if (name.casecmp_to(property1_name) == 0) {
return true;
} else if (name.casecmp_to(property2_name) == 0) {
return true;
}

return false;
}

pub fn _property_get_revert(_: *Self, name: Godot.StringName, value: *Godot.Variant) bool {
if (name.casecmp_to(property1_name) == 0) {
value.* = Godot.Variant.initFrom(Vec3.new(42, 42, 42));
return true;
} else if (name.casecmp_to(property2_name) == 0) {
value.* = Godot.Variant.initFrom(Vec3.new(24, 24, 24));
return true;
}

return false;
}

pub fn _set(self: *Self, name: Godot.StringName, value: Godot.Variant) bool {
if (name.casecmp_to(property1_name) == 0) {
self.property1 = value.as(Vec3);
return true;
} else if (name.casecmp_to(property2_name) == 0) {
self.property2 = value.as(Vec3);
return true;
}

return false;
}

pub fn _get(self: *Self, name: Godot.StringName, value: *Godot.Variant) bool {
if (name.casecmp_to(property1_name) == 0) {
value.* = Godot.Variant.initFrom(self.property1);
return true;
} else if (name.casecmp_to(property2_name) == 0) {
value.* = Godot.Variant.initFrom(self.property2);
return true;
}

return false;
}

pub fn _to_string(_: *Self) ?Godot.String {
return Godot.String.initFromLatin1Chars("ExampleNode");
}
54 changes: 54 additions & 0 deletions zig/src/GuiNode.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const std = @import("std");
const Godot = @import("godot");
const Vec2 = Godot.Vector2;
const Self = @This();

pub usingnamespace Godot.Control;
base: Godot.Control,

sprite: Godot.Sprite2D,

pub fn _enter_tree(self: *Self) void {
if (Godot.Engine.getSingleton().is_editor_hint()) return;

var normal_btn = Godot.initButton();
self.add_child(normal_btn, false, Godot.Node.INTERNAL_MODE_DISABLED);
normal_btn.set_position(Vec2.new(100, 20), false);
normal_btn.set_size(Vec2.new(100, 50), false);
normal_btn.set_text("Press Me");

var toggle_btn = Godot.initCheckBox();
self.add_child(toggle_btn, false, Godot.Node.INTERNAL_MODE_DISABLED);
toggle_btn.set_position(Vec2.new(320, 20), false);
toggle_btn.set_size(Vec2.new(100, 50), false);
toggle_btn.set_text("Toggle Me");

Godot.connect(toggle_btn, "toggled", self, "on_toggled");
Godot.connect(normal_btn, "pressed", self, "on_pressed");

const resource_loader = Godot.ResourceLoader.getSingleton();
const res_name = Godot.String.initFromLatin1Chars("res://textures/logo.png");
const texture = resource_loader.load(res_name, "", Godot.ResourceLoader.CACHE_MODE_REUSE);
if (texture) |tex| {
defer _ = Godot.unreference(tex);
self.sprite = Godot.initSprite2D();
self.sprite.set_texture(tex);
self.sprite.set_position(Vec2.new(400, 300));
self.sprite.set_scale(Vec2.new(0.6, 0.6));
self.add_child(self.sprite, false, Godot.Node.INTERNAL_MODE_DISABLED);
}
}

pub fn _exit_tree(self: *Self) void {
_ = self;
}

pub fn on_pressed(self: *Self) void {
_ = self;
std.debug.print("on_pressed \n", .{});
}

pub fn on_toggled(self: *Self, toggled_on: bool) void {
_ = self;
std.debug.print("on_toggled {any}\n", .{toggled_on});
}
26 changes: 26 additions & 0 deletions zig/src/Reia.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
const std = @import("std");
const Godot = @import("godot");
const builtin = @import("builtin");
const GPA = std.heap.GeneralPurposeAllocator(.{});

var gpa = GPA{};

pub export fn my_extension_init(p_get_proc_address: Godot.GDExtensionInterfaceGetProcAddress, p_library: Godot.GDExtensionClassLibraryPtr, r_initialization: [*c]Godot.GDExtensionInitialization) Godot.GDExtensionBool {
const allocator = gpa.allocator();
return Godot.registerPlugin(p_get_proc_address, p_library, r_initialization, allocator, &init, &deinit);
}

fn init(_: ?*anyopaque, p_level: Godot.GDExtensionInitializationLevel) void {
if (p_level != Godot.GDEXTENSION_INITIALIZATION_SCENE) {
return;
}

const ExampleNode = @import("ExampleNode.zig");
Godot.registerClass(ExampleNode);
}

fn deinit(_: ?*anyopaque, p_level: Godot.GDExtensionInitializationLevel) void {
if (p_level == Godot.GDEXTENSION_INITIALIZATION_CORE) {
_ = gpa.deinit();
}
}
Loading

0 comments on commit 3e46f21

Please sign in to comment.