Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
c65af03
tools : add can create basic folder to the tree view
quentin452 Mar 23, 2025
6e8d626
tools : try adding a drag and drop feature ....
quentin452 Mar 23, 2025
dfb1d5d
tools: replace logic in LevelTreeView.on_database_key_changed() to a…
quentin452 Mar 23, 2025
9e25501
tools: fix creating an unit remove manually created folders
quentin452 Mar 23, 2025
912e0ca
tools: made folders sorted before units in level tree
quentin452 Mar 23, 2025
b101279
tools: add persistant folder saving , now need to can drag and drop u…
quentin452 Mar 24, 2025
d481051
tools: fix many bugs but some bugs during drag and dropping remains
quentin452 Mar 24, 2025
16efae3
scripts: fix some nil error from level_editor.lua , step to reproduce…
quentin452 Mar 24, 2025
d4c50da
tools: some bugfixes on on_database_key_changed
quentin452 Mar 24, 2025
2005391
tools: many bug and crashes fix to level tree drag and drop implement…
quentin452 Mar 25, 2025
a0cb1a7
tools: (LevelTreeView) move drag and drop , folder orga , item synchi…
quentin452 Mar 26, 2025
f747c50
tools: save root folder into .level + simplify a bit the code + do no…
quentin452 Mar 26, 2025
dd6fc47
tools: do not use hardcoded values in sync_existing_units_and_sounds …
quentin452 Mar 26, 2025
c362d9b
tools: avoid hardcoded types usage in on_drag_data_get_internal
quentin452 Mar 26, 2025
8dc080c
tools: avoid some hardcoded values in on_drag_data_received_internal
quentin452 Mar 26, 2025
401257d
tools: dedupplicate appending to tree store code
quentin452 Mar 26, 2025
148e38c
tools: fix removing an item from subfolder do not refresh view
quentin452 Mar 26, 2025
3317afc
tools: fix some crashes caused by missing properties in database + mi…
quentin452 Mar 26, 2025
52b576b
tools: avoid some hardcoded checks while creating a folder
quentin452 Mar 26, 2025
407774a
tools: add a todo in level.vala
quentin452 Mar 26, 2025
01a31dc
tools: remove unnecessary checks + inline
quentin452 Mar 26, 2025
30f0b3c
tools: move level tree items synching into a dedicated file
quentin452 Mar 26, 2025
8787baa
tools: support folder renaming
quentin452 Mar 26, 2025
94146e1
tools : revert rename_folder refactor code
quentin452 Mar 26, 2025
7f3dbc3
add todos
quentin452 Mar 26, 2025
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
8 changes: 6 additions & 2 deletions samples/core/editors/level_editor/level_editor.lua
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,9 @@ end

function Selection:clear()
for k, v in pairs(self._ids) do
LevelEditor._objects[v]:on_selected(false)
if LevelEditor._objects[v] ~= nil then
LevelEditor._objects[v]:on_selected(false)
end
end
self._ids = {}
end
Expand Down Expand Up @@ -285,7 +287,9 @@ end
function Selection:set(ids)
self:clear()
for k, v in pairs(ids) do
LevelEditor._objects[v]:on_selected(true)
if LevelEditor._objects[v] ~= nil then
LevelEditor._objects[v]:on_selected(true)
end
end
self._ids = ids
end
Expand Down
41 changes: 26 additions & 15 deletions tools/core/guid.vala
Original file line number Diff line number Diff line change
Expand Up @@ -13,23 +13,34 @@ public struct Guid

public static Guid new_guid()
{
// FIXME: Replace Rand with something better.
Rand rnd = new Rand();
uint64 a = rnd.next_int();
uint64 b = rnd.next_int();
uint64 c = rnd.next_int();
uint64 d = rnd.next_int();
Guid new_guid = { 0, 0 };

uint64 d1;
d1 = a << 32;
d1 |= b << 0;
uint64 d2;
d2 = c << 32;
d2 |= d << 0;
do
{
// FIXME: Replace Rand with something better.
Rand rnd = new Rand();
uint64 a = rnd.next_int();
uint64 b = rnd.next_int();
uint64 c = rnd.next_int();
uint64 d = rnd.next_int();

uint64 d1;
d1 = a << 32;
d1 |= b << 0;
uint64 d2;
d2 = c << 32;
d2 |= d << 0;

d1 = (d1 & 0xffffffffffff4fffu) | 0x4000u;
d2 = (d2 & 0x3fffffffffffffffu) | 0x8000000000000000u;

new_guid = { d1, d2 };
}
while (new_guid == GUID_NONE_FOLDER
|| new_guid == GUID_UNIT_FOLDER
|| new_guid == GUID_SOUND_FOLDER);

d1 = (d1 & 0xffffffffffff4fffu) | 0x4000u;
d2 = (d2 & 0x3fffffffffffffffu) | 0x8000000000000000u;
return { d1, d2 };
return new_guid;
}

public static Guid parse(string guid)
Expand Down
116 changes: 107 additions & 9 deletions tools/level_editor/level.vala
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,28 @@
* Copyright (c) 2012-2025 Daniele Bartolini et al.
* SPDX-License-Identifier: GPL-3.0-or-later
*/

using Gee;

namespace Crown
{
/// Manages objects in a level.
public class Level
{
public class Folder
{
public Guid id { get; set; }
public string name { get; set; }
public Guid parent_id { get; set; }

// Constructor
public Folder(Guid id, string name, Guid parent_id = GUID_ZERO)
{
this.id = id;
this.name = name;
this.parent_id = parent_id;
}
}

public Project _project;

// Engine connections
Expand All @@ -31,13 +45,17 @@ public class Level
public double _camera_orthographic_size;
public double _camera_target_distance;
public CameraViewType _camera_view_type;
public Gee.ArrayList<Folder> _folders;

// Signals
public signal void selection_changed(Gee.ArrayList<Guid?> selection);
public signal void object_editor_name_changed(Guid object_id, string name);
public signal void level_loaded();

public Level(Database db, RuntimeInstance runtime, Project project)
{
_folders = new Gee.ArrayList<Folder>();

_project = project;

// Engine connections
Expand Down Expand Up @@ -89,6 +107,7 @@ public class Level
camera_decode();
GLib.Application.get_default().activate_action("camera-view", new GLib.Variant.int32(_camera_view_type));


_name = name;
_path = path;

Expand All @@ -103,19 +122,94 @@ public class Level
// FIXME: hack to keep the LevelTreeView working.
_db.key_changed(_id, "units");

load_folders();

level_loaded();

return 0;
}
public void load_folders() {
_folders.clear();

HashSet<Guid?> folder_ids = _db.get_property_set(_id, "folders", new HashSet<Guid?>());
bool needToSave = false;

foreach (var root_info in get_root_folder_info()) {
needToSave |= ensure_root_folder(folder_ids, root_info.guid, root_info.name, root_info.object_type);
}

if (_path != null && needToSave) {
_db.save(_path, _id);
}

foreach (Guid folder_id in folder_ids) {
_folders.add(load_or_create_folder(folder_id));
}
}

private bool ensure_root_folder(HashSet<Guid?> folder_ids, Guid folder_id, string name, string type) {
if (!folder_ids.contains(folder_id)) {
if (_path != null) {
add_folder(folder_id, name, type, GUID_ZERO);
}
folder_ids.add(folder_id);
return true;
}
return false;
}

private Folder load_or_create_folder(Guid folder_id) {
if (_db.has_object(folder_id)) {
return new Folder(
folder_id,
_db.get_property_string(folder_id, "editor.name"),
_db.get_property_guid(folder_id, "parent_folder")
);
} else {
foreach (var root_info in get_root_folder_info()) {
if (folder_id == root_info.guid) {
// TODO AVOID THIS TO PREVENT "NEED TO SAVE TRIGGER" , but for now its needed to fix crash at Value? item_type = view_i.db.get_property(guid, "_type"); from on_drag_data_get_internal
_db.create(folder_id,root_info.object_type);
_db.set_property(folder_id, "editor.name", root_info.name);
_db.set_property(folder_id, "parent_folder", GUID_ZERO);
_db.set_property(folder_id, "_type", root_info.object_type);
return new Folder(folder_id, root_info.name, GUID_ZERO);
}
}
print("ERROR: Unknown Folder ID - %s", folder_id.to_string());
return null;
}
}

public void save(string name)
{
string path = Path.build_filename(_project.source_dir(), name + ".level");

save_folders();

camera_encode();
_db.save(path, _id);
_path = path;
_name = name;
}

public void save_folders()
{
foreach (Folder folder in _folders) {
_db.set_property_string(folder.id, "editor.name", folder.name);
_db.set_property_guid(folder.id, "parent_folder", folder.parent_id);
_db.add_to_set(_id, "folders", folder.id);
}
}
public void add_folder(Guid id, string name, string type, Guid parent_id = GUID_ZERO)
{
_db.create(id, type);
_db.set_property_string(id, "editor.name", name);
_db.set_property_guid(id, "parent_folder", parent_id);
_db.add_to_set(_id, "folders", id);
_folders.add(new Folder(id, name, parent_id));
}

public void spawn_empty_unit()
{
Guid id = Guid.new_guid();
Expand Down Expand Up @@ -176,14 +270,16 @@ public class Level
selection_set(ids);
}

public void on_unit_spawned(Guid id, string? name, Vector3 pos, Quaternion rot, Vector3 scl)
{
Unit unit = Unit(_db, id);
unit.create(name, pos, rot, scl);

_db.set_property_string(id, "editor.name", "unit_%04u".printf(_num_units++));
_db.add_to_set(_id, "units", id);
}
public void on_unit_spawned(Guid id, string? name, Vector3 pos, Quaternion rot, Vector3 scl)
{
Unit unit = Unit(_db, id);
unit.create(name, pos, rot, scl);

_db.set_property_string(id, "editor.name", "unit_%04u".printf(_num_units++));
_db.add_to_set(_id, "units", id);

_db.set_property_guid(id, "parent_folder", GUID_UNIT_FOLDER);
}

public void on_sound_spawned(Guid id, string name, Vector3 pos, Quaternion rot, Vector3 scl, double range, double volume, bool loop)
{
Expand All @@ -192,6 +288,8 @@ public class Level

_db.set_property_string (id, "editor.name", "sound_%04u".printf(_num_sounds++));
_db.add_to_set(_id, "sounds", id);

_db.set_property_guid(id, "parent_folder", GUID_SOUND_FOLDER);
}

public void on_move_objects(Guid?[] ids, Vector3[] positions, Quaternion[] rotations, Vector3[] scales)
Expand Down
Loading
Loading