Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added assets/cubyz/ui/edit_icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion src/gui/components/TextInput.zig
Original file line number Diff line number Diff line change
Expand Up @@ -435,6 +435,7 @@ pub fn inputCharacter(self: *TextInput, character: u21) void {
}

pub fn setString(self: *TextInput, utf8EncodedString: []const u8) void {
if (self.options.disabled) return;
self.clear();
self.currentString.insertSlice(0, utf8EncodedString);
self.reloadText();
Expand Down Expand Up @@ -568,7 +569,6 @@ pub fn render(self: *TextInput, mousePosition: Vec2f) void {
self.showCursor = !self.showCursor;
}
}

if (self.showCursor and !self.options.disabled) {
const oldColor = draw.setColor(0xff000000);
defer draw.restoreColor(oldColor);
Expand Down
1 change: 1 addition & 0 deletions src/gui/windows/_list.zig
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub const debug_vulkan_info = @import("debug_vulkan_info.zig");
pub const debug = @import("debug.zig");
pub const delete_world_confirmation = @import("delete_world_confirmation.zig");
pub const download_controller_mappings = @import("download_controller_mappings.zig");
pub const edit_world = @import("edit_world.zig");
pub const energybar = @import("energybar.zig");
pub const error_prompt = @import("error_prompt.zig");
pub const gpu_performance_measuring = @import("gpu_performance_measuring.zig");
Expand Down
196 changes: 196 additions & 0 deletions src/gui/windows/edit_world.zig
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
const std = @import("std");

const build_options = @import("build_options");

const main = @import("main");
const Vec2f = main.vec.Vec2f;
const NeverFailingAllocator = main.heap.NeverFailingAllocator;
const ZonElement = main.ZonElement;

const gui = @import("../gui.zig");
const GuiWindow = gui.GuiWindow;
const Button = @import("../components/Button.zig");
const Label = @import("../components/Label.zig");
const TextInput = @import("../components/TextInput.zig");
const HorizontalList = @import("../components/HorizontalList.zig");
const VerticalList = @import("../components/VerticalList.zig");
const CheckBox = @import("../components/CheckBox.zig");

const Gamemode = main.game.Gamemode;
const defaults = main.server.world_zig.Settings.defaults;

const WorldSettings = struct {
seed: i128,
defaultGamemode: Gamemode,
allowCheats: bool,
testingMode: bool,
localPlayerIndex: usize,

isUpated: bool = false,

pub fn init(seed: i128, defaultgameMode: ?[]const u8, allowCheats: bool, testingMode: bool, localPlayerIndex: usize) WorldSettings {
return .{
.seed = seed,
.defaultGamemode = toEnum(defaultgameMode),
.allowCheats = allowCheats,
.testingMode = testingMode,
.localPlayerIndex = localPlayerIndex,
};
}

fn toEnum(gamemode: ?[]const u8) Gamemode {
const mode = gamemode orelse @tagName(defaults.defaultGamemode);
return std.meta.stringToEnum(Gamemode, mode).?;
}

pub fn print(self: WorldSettings) void {
std.debug.print("name: {s}\nseed: {d}\n defaultGameMode: {s}\nallowCheats: {}\ntestingMode: {}\n", .{
nameInput.currentString.items,
self.seed,
@tagName(self.defaultGamemode),
self.allowCheats,
self.testingMode,
});
}

pub fn update(self: *WorldSettings, value: bool) void {
self.isUpated = value;
saveChanges.disabled = !value;
}
};

pub var window = GuiWindow{
.contentSize = Vec2f{128, 256},
};

const padding: f32 = 8;

var editWorldName: []const u8 = "";

var worldInfo: ZonElement = undefined;
var worldSettings: WorldSettings = undefined;

var nameInput: *TextInput = undefined;
var gamemodeInput: *Button = undefined;
var saveChanges: *Button = undefined;

fn nameCallback() void {
worldSettings.update(true);
}

fn gameModeCallback() void {
worldSettings.defaultGamemode = std.enums.fromInt(Gamemode, @intFromEnum(worldSettings.defaultGamemode) + 1) orelse @enumFromInt(0);
gamemodeInput.child.label.updateText(@tagName(worldSettings.defaultGamemode));
worldSettings.update(true);
}

fn allowCheatsCallback(allow: bool) void {
worldSettings.allowCheats = allow;
worldSettings.update(true);
}

fn testingModeCallback(enabled: bool) void {
worldSettings.testingMode = enabled;
worldSettings.update(true);
}

fn saveChangesCallback() void {
worldSettings.print();

const path = main.stackAllocator.print("saves/{s}/world.zig.zon", .{editWorldName});
defer main.stackAllocator.free(path);

const worldInfoSettings = worldInfo.getChild("settings");

worldInfoSettings.put("defaultGamemode", @tagName(worldSettings.defaultGamemode));
worldInfoSettings.put("allowCheats", worldSettings.allowCheats);
if (!build_options.isTaggedRelease) {
worldInfoSettings.put("testingMode", worldSettings.testingMode);
}

worldInfo.put("localPlayer", worldSettings.localPlayerIndex);
worldInfo.put("name", nameInput.currentString.items);
worldInfo.put("settings", worldInfoSettings.clone(main.globalAllocator));
main.files.cubyzDir().writeZon(path, worldInfo) catch |err| {
std.log.err("Error while creating new world: {s}", .{@errorName(err)});
return;
};
worldSettings.update(false);
gui.closeWindowFromRef(&window);
}

pub fn init() void {
editWorldName = "";
}

pub fn deinit() void {
main.globalAllocator.free(editWorldName);
}

pub fn setEditWorldName(name: []const u8) void {
main.globalAllocator.free(editWorldName);
editWorldName = main.globalAllocator.dupe(u8, name);
}

pub fn onOpen() void {
const worldInfoPath = main.stackAllocator.print("saves/{s}/world.zig.zon", .{editWorldName});
defer main.stackAllocator.free(worldInfoPath);

worldInfo = main.files.cubyzDir().readToZon(main.globalAllocator, worldInfoPath) catch |err| {
std.log.err("Error while creating new world: {s}", .{@errorName(err)});
return;
};

const worldInfoSettings = worldInfo.getChild("settings");

worldSettings = WorldSettings.init(
worldInfoSettings.get(i128, "seed") orelse 0,
worldInfoSettings.get([]const u8, "defaultGamemode"),
worldInfoSettings.get(bool, "allowCheats") orelse defaults.allowCheats,
worldInfoSettings.get(bool, "testingMode") orelse defaults.testingMode,
worldInfo.get(usize, "localPlayer") orelse 0,
);

const list = VerticalList.init(.{padding, 16 + padding}, 300, 8);

list.add(Label.init(.{0, 0}, 128, "Edit World", .center));

nameInput = TextInput.init(.{0, 0}, 128, 22, "", .{.onNewline = .init(nameCallback)});
list.add(nameInput);

gamemodeInput = Button.initText(.{0, 0}, 128, @tagName(worldSettings.defaultGamemode), .{.onAction = .init(gameModeCallback)});
list.add(gamemodeInput);

list.add(CheckBox.init(.{0, 0}, 128, "Allow Cheats", worldSettings.allowCheats, &allowCheatsCallback));

if (!build_options.isTaggedRelease) {
list.add(CheckBox.init(.{0, 0}, 128, "Testing Mode", worldSettings.testingMode, &testingModeCallback));
}

const seed = main.stackAllocator.print("{d}", .{worldSettings.seed});
defer main.stackAllocator.free(seed);
const seedLabel = Label.init(.{0, 0}, 48, "Seed:", .left);
const seedInput = TextInput.init(.{0, 0}, 128 - 48, 22, seed, .{.disabled = true});
const seedRow = HorizontalList.init();
seedRow.add(seedLabel);
seedRow.add(seedInput);
list.add(seedRow);

const indexLabel = Label.init(.{0, 0}, 128, "Local Player Indiex", .left);
list.add(indexLabel);

saveChanges = Button.initText(.{0, 0}, 128, "Save Changes", .{.disabled = !worldSettings.isUpated, .onAction = .init(saveChangesCallback)});
list.add(saveChanges);

list.finish(.center);
window.rootComponent = list.toComponent();
window.contentSize = window.rootComponent.?.pos() + window.rootComponent.?.size() + @as(Vec2f, @splat(padding));
gui.updateWindowPositions();
}

pub fn onClose() void {
if (window.rootComponent) |*comp| {
comp.deinit();
}
worldInfo.deinit(main.globalAllocator);
}
14 changes: 12 additions & 2 deletions src/gui/windows/save_selection.zig
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ pub var mode: main.server.ServerWorld.Mode = undefined;

var deleteIcon: Texture = undefined;
var fileExplorerIcon: Texture = undefined;
var editIcon: Texture = undefined;

const WorldInfo = struct {
lastUsedTime: i64,
Expand All @@ -41,11 +42,13 @@ var worldList: main.List(WorldInfo) = .empty;
pub fn init() void {
deleteIcon = Texture.initFromFile("assets/cubyz/ui/delete_icon.png");
fileExplorerIcon = Texture.initFromFile("assets/cubyz/ui/file_explorer_icon.png");
editIcon = Texture.initFromFile("assets/cubyz/ui/edit_icon.png");
}

pub fn deinit() void {
deleteIcon.deinit();
fileExplorerIcon.deinit();
editIcon.deinit();
}

pub fn openWorld(name: []const u8) void {
Expand Down Expand Up @@ -100,6 +103,12 @@ fn openFolder(index: usize) void {
main.files.openDirInWindow(path);
}

fn editWorld(index: usize) void {
main.gui.closeWindow("edit_world");
main.gui.windowlist.edit_world.setEditWorldName(worldList.items[index].fileName);
main.gui.openWindow("edit_world");
}

pub fn update() void {
if (needsUpdate) {
needsUpdate = false;
Expand Down Expand Up @@ -154,8 +163,9 @@ pub fn onOpen() void {
for (worldList.items, 0..) |worldInfo, i| {
const row = HorizontalList.init();
row.add(Button.initText(.{0, 0}, 128, worldInfo.name, .{.onAction = .initWithInt(openWorldWrap, i)}));
row.add(Button.initIcon(.{8, 0}, .{16, 16}, fileExplorerIcon, .{.onAction = .initWithInt(openFolder, i)}));
row.add(Button.initIcon(.{8, 0}, .{16, 16}, deleteIcon, .{.onAction = .initWithInt(deleteWorld, i)}));
row.add(Button.initIcon(.{4, 0}, .{16, 16}, editIcon, .{.onAction = .initWithInt(editWorld, i)}));
row.add(Button.initIcon(.{4, 0}, .{16, 16}, fileExplorerIcon, .{.onAction = .initWithInt(openFolder, i)}));
row.add(Button.initIcon(.{4, 0}, .{16, 16}, deleteIcon, .{.onAction = .initWithInt(deleteWorld, i)}));
row.finish(.{0, 0}, .center);
list.add(row);
}
Expand Down
Loading