mirror of
https://github.com/Dingo-Shenanigans/ReSkate.git
synced 2026-10-18 06:05:15 +02:00
Sets: save a selection under a name and place it again anywhere, on any map. - The library gets an OBJECTS / SETS switch. SETS saves the selected objects as a set and lists the saved sets to place or delete (Delete asks for a second press). - A set is a park file in <profile>/object_sets/<name>.park.json, so it shares the park format, its 2 MB limit and its name rules. Positions are relative to the set's anchor: the middle of its footprint, at its lowest origin. - Placing follows the cursor as one wire cube per object, on surfaces or the grid plane; the mouse wheel turns it by the angle step. A click pastes the whole set: one undo step, under the paste path's object and session limits. Sets with objects missing from the catalog cannot be placed. - A placed or pasted group is then selected with the move gizmo. Editing groups: - Local axes work for multi-selections. A placed set's axes are the rotation it was placed with, plus every later turn; any other group uses its last selected object's rotation. Applying a moved group does not snap its own rotation to the angle grid. - Duplicate (button or Ctrl+D) copies every selected object at its saved position, rotation and scale, one grid step along X, as one paste. - On a server with object scaling off, pastes (sets, duplicates, Ctrl+V) are made at 1x. Tests cover set storage (anchor, round trip, replace, names, damaged files, delete), saving and placing a set through the UI (surface, wheel, one paste, no live preview), selecting it with its own axes, moving it along them, and duplicating with and without scaling. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
71 lines
3.6 KiB
C++
71 lines
3.6 KiB
C++
#pragma once
|
|
#include "Extension/Objects/ParkEditor/editor_math.h"
|
|
#include "overlay.h"
|
|
#include <imgui.h>
|
|
#include <optional>
|
|
|
|
namespace dingosdk::overlay {
|
|
enum class ParkTransformMode { move, rotate, scale };
|
|
struct ParkEditorUI {
|
|
std::uint64_t generation{}, selected{}, draft_revision{}, queued_revision{};
|
|
std::array<char, 128> search{};
|
|
// PARK PROJECT dialog: the selected mod folder ("" = a new mod) and the
|
|
// form, filled from the selection whenever it changes.
|
|
bool project_open{};
|
|
std::string project_selected, project_fields_for;
|
|
std::array<char, 65> mod_title{}, mod_author{};
|
|
std::array<char, 33> mod_version{};
|
|
std::array<char, 513> mod_description{};
|
|
std::string category, placing, feedback, queued_status;
|
|
editor::Vec3 position{}, angles{}, drag_start{}, drag_axis{};
|
|
editor::Quat drag_rotation{0, 0, 0, 1};
|
|
bool scaling_allowed{true}; // off: the server shares objects at their own size, so none is resized here
|
|
float scale{1}, grid{.5f}, angle_snap{15}, scale_snap{.1f}, plane_height{}, distance{10},
|
|
drag_parameter{}, drag_angle{}, drag_scale{1}, drag_gizmo_scale{1};
|
|
ParkTransformMode mode{ParkTransformMode::move};
|
|
bool snapping{true}, local_axes{}, pending{}, inspector_dirty{}, initialized{}, flying{},
|
|
exit_pending{};
|
|
int dragging{-1};
|
|
double queued_at{}, exit_at{}, feedback_until{};
|
|
EditorSurfaceRequest surface_request;
|
|
bool surface_mode{true}, surface_confirm{}, surface_valid{};
|
|
float surface_offset{};
|
|
double next_surface_request{};
|
|
std::vector<std::uint64_t> selection;
|
|
std::vector<EditorTransform> drag_objects;
|
|
editor::Vec3 drag_pivot{}, free_offset{};
|
|
editor::Quat drag_orientation{0, 0, 0, 1};
|
|
std::uint64_t preview_token{}, preview_sequence{}, preview_revision{}, next_preview_token{};
|
|
double preview_heartbeat{};
|
|
editor::Vec3 preview_position{}, preview_angles{};
|
|
float preview_scale{1};
|
|
bool preview_place{}, asset_drag{}, pick_confirm{}, pick_shift{}, free_anchor{}, free_release{};
|
|
double selection_heartbeat{};
|
|
std::vector<std::uint64_t> highlighted;
|
|
std::vector<EditorObject> clipboard, paste_expected;
|
|
std::vector<std::uint64_t> paste_before;
|
|
unsigned paste_serial{};
|
|
// Saved object sets: the library lists them in place of objects. `placing_set` follows the
|
|
// cursor at ui.position / ui.angles / ui.scale until a click pastes it; `set_delete` is
|
|
// the set whose Delete was pressed once and waits for the confirming press.
|
|
bool library_sets{};
|
|
std::string placing_set, set_delete;
|
|
// A multi-selection's own orientation, for its local axes and its Rotation field: a placed set
|
|
// starts at the rotation it was placed with and keeps every turn given to it. Any other group
|
|
// uses its active (last selected) object's rotation. `group_angles` is what the field showed.
|
|
std::vector<std::uint64_t> group_ids; // sorted
|
|
editor::Quat group_rotation{0, 0, 0, 1};
|
|
std::optional<editor::Quat> paste_rotation; // the set being pasted
|
|
editor::Vec3 group_angles{};
|
|
std::array<char, 65> set_name{};
|
|
// Look shared with the ReSkate menu, set by the overlay before drawing.
|
|
// Null fonts fall back to the current font (the UI tests pass none).
|
|
ImFont *title_font{}, *bold_font{}, *heading_font{};
|
|
float ui_scale{1};
|
|
std::string close_key{"INS"};
|
|
};
|
|
// Render thread only. Returns whether the viewport currently owns flight input.
|
|
bool draw_park_editor(ParkEditorUI &, const Model &, const CallbacksV3 &, bool console_open,
|
|
bool exit_requested, bool &menu_visible);
|
|
} // namespace dingosdk::overlay
|