Skip to content

Commit

Permalink
Progress into user friendly symmetry
Browse files Browse the repository at this point in the history
  • Loading branch information
tatjam committed Mar 17, 2023
1 parent 0b9e7a1 commit bdb9057
Show file tree
Hide file tree
Showing 20 changed files with 169 additions and 45 deletions.
8 changes: 8 additions & 0 deletions res/.luadef/definitions/editor.lua
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,11 @@ local symmetry_panel = {}
---@param can_exit boolean Is the symmetry done being created (show done button)
---@param can_go_back boolean Can the current action be "cancelled" (show back instead of cancel)
function symmetry_panel:set_canvas(canvas, can_exit, can_go_back) end

---@class vehicle_editor.vehicle
local editor_vehicle = {}

---@param p vehicle.piece
--- Call this function after moving pieces or similar so their colliders are correctly placed
--- Updates all children pieces too!
function editor_vehicle:update_collider_hierarchy(p) end
34 changes: 22 additions & 12 deletions res/.luadef/script_types/symmetry_script.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,32 @@

---@class symmetry_mode
---@field saved_toml toml.table Modify this table to save data, at start it contains serialized data
local symmetry_mode_type = {}
---@param count integer Number of clones to make, including the already existing piece
---@return vehicle.piece[] Clones including the already existing piece
--- Remember to call editor_vehicle:update_collider_hierarchy(clone) after you have positioned the clones!
function symmetry_mode_type:make_clones(count) end

---@return vehicle.piece
function symmetry_mode_type:get_root() end

---@return string Name of the attachment marker
function symmetry_mode_type:get_attachment() end

---@return vehicle.piece[]
function symmetry_mode_type:get_all_pieces() end


---@class vehicle_editor.modify_interface
local modify_interface_type = {}
---@param allow_non_radial boolean If true, allows picking pieces which dont allow radial attachment
function modify_interface_type:start_picking_piece(allow_non_radial) end
---@param forbidden_pieces vehicle.piece[] A list of pieces which may not be picked (a good default in symmetry_mode:get_all_pieces())
function modify_interface_type:start_picking_piece(allow_non_radial, forbidden_pieces) end


---@type symmetry_mode The symmetry group being implemented
symmetry_mode = {}

---@param count integer Number of clones to make, including the already existing piece
---@return vehicle.piece[] Clones including the already existing piece
function symmetry_mode:make_clones(count) end

---@return vehicle.piece
function symmetry_mode:get_root() end

---@return string Name of the attachment marker
function symmetry_mode:get_attachment() end

---@type vehicle_editor.symmetry_panel
--- Not available if take_gui_control was not called!
symmetry_panel = nil
Expand All @@ -34,4 +41,7 @@ modify_interface = nil
edveh_interface = nil

---@type vehicle
vehile = nil
vehicle = nil

---@type vehicle_editor.vehicle
editor_vehicle = nil
28 changes: 19 additions & 9 deletions res/core/scenes/editor/symmetry/radial_piece.lua
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ local select_piece_canvas = nil
local function get_piece_radius(piece)
-- We try to use radius metadata for given axis, if not available then we are forced to use AABBs
-- which may not always be accurate
--local has_meta = piece.prototype.metadata:contains("radial_symmetry_radius")
local has_meta = piece.prototype.metadata:contains("radial_symmetry_radius")
if has_meta then
return piece.prototype.metadata:get_number("radial_symmetry_radius")
else
Expand Down Expand Up @@ -67,19 +67,25 @@ local function rebuild()
offset.y = math.sin(angle) * radius
offset.z = 0.0

local rotoffset = glm.rotate(glm.mat4.new(), angle, glm.vec3.new(0, 0, 1))
local axis = glm.rotate_from_to(glm.vec3.new(0, 0, 1), center:get_forward())
logger.info(center:get_up())
local axis_quat = glm.quat.new(axis)
-- We set the piece looking at the rotation, with Z up
-- (same behaviour as radial attachment)
local rot = glm.quat_look_at(glm.vec3.new(0, 0, 0), offset, glm.vec3.new(0, 0, 1), glm.vec3.new(0, 1, 0))

local tform = center:get_graphics_transform()
local pos = tform.pos
local rot = glm.quat.new(rotoffset)

local tform = center:get_graphics_transform()
local pos = axis_quat * offset + tform.pos
local root = symmetry_mode:get_root()
local attach = root:get_attachment(symmetry_mode:get_attachment()).marker

-- Attach a root piece clone at given position
vehicle:move_piece(clone, pos + offset, rot, attach)
-- clone:attach_to(center, symmetry_mode:get_attachment(), "")
vehicle:move_piece(clone, pos, axis_quat * rot, attach)
clone:attach_to(center, symmetry_mode:get_attachment(), "")
editor_vehicle:update_collider_hierarchy(clone)


end

vehicle:update_attachments()
Expand All @@ -100,10 +106,14 @@ local function select_piece(piece_id, attachment)
end

local function pick_piece()
symmetry_panel:set_canvas(select_piece_canvas, false, true)
modify_interface:start_picking_piece(false)
symmetry_panel:set_canvas(select_piece_canvas, false, center_piece_id > 0)
modify_interface:start_picking_piece(false, symmetry_mode:get_all_pieces())
events:add_named(edveh_interface, "on_select_piece", "select_center", select_piece)
end

function gui_go_back()
symmetry_panel:set_canvas(main_canvas, true, false)
events:remove("select_center")
end

local function make_main_canvas()
Expand Down
7 changes: 7 additions & 0 deletions res/core/util/c_events.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
-- A more comfortable method to handle events, extremely simple
require("events")
local events = {}

events.handlers = {}
Expand All @@ -19,11 +20,17 @@ function events:add(emitter, event, func)
end

function events:remove_all()
for _, handler in pairs(self.handlers) do
handler:sign_out()
end
self.handlers = {}
end

---@param id string Name of the event id to remove
function events:remove(id)
if self.handlers[id] then
self.handlers[id]:sign_out()
end
self.handlers[id] = nil
end

Expand Down
1 change: 1 addition & 0 deletions src/assets/PartPrototype.h
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ struct PiecePrototype
this->to_attachment = b.to_attachment;
this->aabb_min = b.aabb_min;
this->aabb_max = b.aabb_max;
this->metadata = b.metadata;
}

PiecePrototype(GPUModelNodePointer&& n) : model_node(std::move(n))
Expand Down
10 changes: 10 additions & 0 deletions src/game/scenes/editor/EditorVehicle.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,16 @@ void EditorVehicle::draw_attachment(std::pair<PieceAttachment, bool>& pair, Piec

}

void EditorVehicle::update_collider_hierarchy(Piece *p)
{
std::vector<Piece*> children = veh->get_children_of(p);
update_collider(p);
for(Piece* child : children)
{
update_collider(child);
}
}


void GenericSerializer<EditorVehicle>::serialize(const EditorVehicle& what, cpptoml::table& target)
{
Expand Down
1 change: 1 addition & 0 deletions src/game/scenes/editor/EditorVehicle.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class EditorVehicle : public Drawable
public:

void update_collider(Piece* p);
void update_collider_hierarchy(Piece* p);
// Does not delete the piece_meta
void remove_collider(Piece* p);

Expand Down
2 changes: 2 additions & 0 deletions src/game/scenes/editor/gui/EditorPartList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@ void EditorPartList::create_part(AssetHandle<PartPrototype>& proto)

scene->part_id++;
n_part->id = scene->part_id;
veh->id_to_part[n_part->id] = n_part;

n_part->vehicle = veh;
std::vector<Piece*> n_pieces = n_part->create_pieces();
Expand All @@ -95,6 +96,7 @@ void EditorPartList::create_part(AssetHandle<PartPrototype>& proto)
{
scene->piece_id++;
p->id = scene->piece_id;
veh->id_to_piece[p->id] = p;
}

// Find a space for plumbing and put it there IF IT HAS PLUMBING
Expand Down
40 changes: 40 additions & 0 deletions src/game/scenes/editor/gui/ModifyPanel.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ void ModifyPanel::change_state(ModifyInterface::State st, Piece* selected_piece)

// Create the symmetry mode proper in the vehicle
modifying_symmetry = new SymmetryMode();
sc->vehicle->veh->meta.symmetry_modes.push_back(modifying_symmetry);

auto config = AssetHandle<Config>(creating_symmetry_name);
config->read_to(*modifying_symmetry);
// We initialize the symmetry mode without any config, as it's being created
Expand Down Expand Up @@ -179,9 +181,42 @@ void ModifyPanel::make_symmetry_canvas_creating()
auto layout = std::make_shared<GUIVerticalLayout>();
auto str = osp->game_database->get_string("core:cancel");
cancel_button = std::make_shared<GUITextButton>(str);
cancel_button->sign_up_for_event("on_clicked", EventHandler([this](EventArguments& args)
{
if(cancel_goes_back)
{
modifying_symmetry->gui_go_back();
}
else
{
// Remove the symmetry mode which has not been created
std::vector<SymmetryMode*>& array = sc->vehicle->veh->meta.symmetry_modes;
int i = -1;
for(i = 0; i < array.size(); i++)
{
if(array[i] == modifying_symmetry)
{
break;
}
}
logger->check(i >= 0);
array.erase(array.begin() + i);
modifying_symmetry->leave_gui_control();
delete modifying_symmetry;
modifying_symmetry = nullptr;
mod_int->change_state(ModifyInterface::IDLE);
}
}));
layout->add_widget(cancel_button);
auto str2 = osp->game_database->get_string("core:finish");
finish_button = std::make_shared<GUITextButton>(str2);
finish_button->sign_up_for_event("on_clicked", EventHandler([this](EventArguments& args)
{
// Exit, the symmetry mode is saved in the vehicle
mod_int->change_state(ModifyInterface::IDLE);
modifying_symmetry->leave_gui_control();
modifying_symmetry = nullptr;
}));
layout->mark_same_line();
layout->add_widget(finish_button);
bottom->set_layout(layout);
Expand All @@ -194,9 +229,14 @@ void ModifyPanel::set_symmetry_canvas(std::shared_ptr<GUICanvas> canvas, bool ca

std::string back;
if(can_go_back)
{
back = osp->game_database->get_string("core:back");
cancel_goes_back = true;
}
else
{
cancel_goes_back = false;

if(mod_int->cur_state == ModifyInterface::SELECTING_SYMMETRY)
{
back = osp->game_database->get_string("core:undo");
Expand Down
1 change: 1 addition & 0 deletions src/game/scenes/editor/gui/ModifyPanel.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ class ModifyPanel : public EditorPanel
std::shared_ptr<GUITextButton> cancel_button;

std::string creating_symmetry_name;
bool cancel_goes_back;

public:

Expand Down
18 changes: 7 additions & 11 deletions src/game/scenes/editor/interfaces/ModifyInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -220,8 +220,9 @@ std::vector<Piece*> ModifyInterface::highlight_symmetry(Piece* root)
return children;
}

void ModifyInterface::start_picking_piece(bool allow_only_radial)
void ModifyInterface::start_picking_piece(bool allow_only_radial, std::vector<Piece*> forbidden)
{
forbidden_pieces = forbidden;
only_radial_allowed = allow_only_radial;
if(cur_state == CREATING_SYMMETRY)
{
Expand All @@ -238,16 +239,11 @@ bool ModifyInterface::do_interface_modify_symmetry(Piece *hovered, GUIInput *ipt
auto children = highlight_symmetry(selected_piece);
if(pick_another_piece && hovered)
{
bool is_in_symmetry = false;
for(Piece* p : children)
{
if(p == hovered)
{
is_in_symmetry = true;
break;
}
}
if((hovered->piece_prototype->allows_radial || !only_radial_allowed) && !is_in_symmetry && hovered != selected_piece)
bool is_forbidden = vector_contains(forbidden_pieces, hovered);
is_forbidden |= vector_contains(children, hovered);
is_forbidden |= selected_piece == hovered;

if((hovered->piece_prototype->allows_radial || !only_radial_allowed) && !is_forbidden && hovered != selected_piece)
{
edveh->piece_meta[hovered].highlight = glm::vec3(1.0f);

Expand Down
5 changes: 4 additions & 1 deletion src/game/scenes/editor/interfaces/ModifyInterface.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ class ModifyInterface : public BaseInterface
};
Piece* selected_piece;
int cur_attachment_point;
// Never allows children of selected_piece either!
std::vector<Piece*> forbidden_pieces;

// If true and we are creating symmetry, more pieces may be picked and returned
// using the select_piece event (used by lua)
bool pick_another_piece;
Expand All @@ -64,7 +67,7 @@ class ModifyInterface : public BaseInterface

bool can_leave() override;

void start_picking_piece(bool only_radial_allowed);
void start_picking_piece(bool only_radial_allowed, std::vector<Piece*> forbidden);

ModifyInterface(EditorVehicleInterface* edveh_int);
};
5 changes: 4 additions & 1 deletion src/lua/libs/LuaEditor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ void LuaEditor::load_to(sol::table& table)
},
EVENT_EMITTER_SIGN_UP(EditorScene));

table.new_usertype<EditorVehicle>("editor_vehicle", sol::no_constructor);
table.new_usertype<EditorVehicle>("editor_vehicle", sol::no_constructor,
"update_collider", &EditorVehicle::update_collider,
"update_collider_hierarchy", &EditorVehicle::update_collider_hierarchy);
table.new_usertype<EditorCamera>("editor_camera", sol::no_constructor,
"get_camera_uniforms", &EditorCamera::get_camera_uniforms);

Expand All @@ -34,6 +36,7 @@ void LuaEditor::load_to(sol::table& table)
table.new_usertype<SymmetryMode>("symmetry_mode", sol::no_constructor,
"saved_toml", &SymmetryMode::save_toml,
"make_clones", &SymmetryMode::make_clones,
"get_all_pieces", [](SymmetryMode* s){ return s->all_in_symmetry; },
"get_root", [](SymmetryMode* mod)
{
return mod->root;
Expand Down
1 change: 1 addition & 0 deletions src/lua/libs/LuaEvents.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ struct LuaEventHandler

void sign_out()
{
logger->info("Signing out");
if(signed_up)
{
signed_up = false;
Expand Down
8 changes: 6 additions & 2 deletions src/universe/Events.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "Events.h"
#include <util/Logger.h>

std::unordered_set<EventHandler, EventHandlerHasher>& EventEmitter::index_event_receivers(const std::string& str)
{
Expand All @@ -16,9 +17,12 @@ std::unordered_set<EventHandler, EventHandlerHasher>& EventEmitter::index_event_

void EventEmitter::emit_event(const std::string& event_id, EventArguments args)
{
auto& rc = index_event_receivers(event_id);
// We make a copy for safe iteration, as elements may be removed during iteration
// Note that this means that removing an event handler during event call
// will only have effect on next event!
auto rc = index_event_receivers(event_id);

for (const EventHandler& ev : rc)
for (auto& ev : rc)
{
ev.fnc(args);
}
Expand Down
1 change: 1 addition & 0 deletions src/universe/Events.h
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ class EventEmitter
private:
std::unordered_map<std::string, std::unordered_set<EventHandler, EventHandlerHasher>> event_receivers;
std::unordered_set<EventHandler, EventHandlerHasher>& index_event_receivers(const std::string& str);

public:

void sign_up_for_event(const std::string& event_id, EventHandler id);
Expand Down
Loading

0 comments on commit bdb9057

Please sign in to comment.