45 if(play && play->is_active())
47 error =
"Scene is in play mode; mutating tools are disabled";
53 if(!out_scene || !out_scene->registry)
55 error =
"No active scene";
61inline auto read_string(
const simdjson::dom::object& args,
const char* key, std::string& out) ->
bool
63 std::string_view
view;
64 if(args[key].get(
view))
72inline auto read_bool(
const simdjson::dom::object& args,
const char* key,
bool& out) ->
bool
75 if(args[key].get(value))
83inline auto read_double(
const simdjson::dom::object& args,
const char* key,
double& out) ->
bool
86 if(args[key].get(value))
94inline auto read_vec3(
const simdjson::dom::object& args,
const char* key, math::vec3& out) ->
bool
96 simdjson::dom::array arr;
97 if(args[key].get(arr))
101 std::vector<double> values;
111 if(values.size() != 3)
115 out = math::vec3{
static_cast<float>(values[0]),
static_cast<float>(values[1]),
static_cast<float>(values[2])};
121 return R
"({"type":"object","properties":{}})";
127 if(play && play->is_active())
129 error =
"Editor is in play mode; this tool is disabled";
139 error =
"No project open";
148 out_is_local =
false;
150 if(!
read_string(args,
"space", space) || space.empty() || space ==
"world" || space ==
"global")
152 out_is_local =
false;
160 error =
"Invalid space (use \"world\" or \"local\")";
176 out.has_position =
read_vec3(obj,
"position", out.position);
177 out.has_rotation =
read_vec3(obj,
"rotation_euler", out.rotation_euler);
178 out.has_scale =
read_vec3(obj,
"scale", out.scale);
234inline auto read_wait_ms(
const simdjson::dom::object& args, int64_t default_ms = 1000) -> std::chrono::milliseconds
236 int64_t wait_ms = default_ms;
237 if(args[
"wait_ms"].get(wait_ms))
239 wait_ms = default_ms;
249 return std::chrono::milliseconds(wait_ms);
254 if(wait_ms.count() > 0)
256 std::this_thread::sleep_for(wait_ms);
262 std::transform(value.begin(),
267 return static_cast<char>(std::tolower(c));
272inline auto contains_ci(std::string_view haystack, std::string_view needle) ->
bool
280 return h.find(n) != std::string::npos;
283inline auto starts_with(std::string_view value, std::string_view prefix) ->
bool
285 return value.size() >= prefix.size() && value.compare(0, prefix.size(), prefix) == 0;
290 const auto center = bounds.get_center();
291 const auto extents = bounds.get_extents();
293 R
"({{"min":[{:.6g},{:.6g},{:.6g}],"max":[{:.6g},{:.6g},{:.6g}],"center":[{:.6g},{:.6g},{:.6g}],"extents":[{:.6g},{:.6g},{:.6g}]}})",
311 while(!
type.empty() && (
type.front() ==
'*' ||
type.front() ==
'.'))
313 if(
type.front() ==
'*')
320 if(!
type.empty() &&
type.front() !=
'.')
325 if(
type ==
".prefab")
329 if(
type ==
".mesh" ||
type ==
".model")
333 if(
type ==
".material")
337 if(
type ==
".texture" ||
type ==
".tex")
341 if(
type ==
".audio" ||
type ==
".audioclip")
349 if(
type ==
".physics" ||
type ==
".phxmat" ||
type ==
".physics_material")
358 if(protocol ==
"app" || protocol ==
"app:/")
362 if(protocol ==
"engine" || protocol ==
"engine:/")
366 if(protocol ==
"editor" || protocol ==
"editor:/")
auto has_open_project() const -> bool
auto get_format(bool include_dot=true) -> std::string
auto require_not_play_mode(rtti::context &ctx, std::string &error) -> bool
auto read_vec3(const simdjson::dom::object &args, const char *key, math::vec3 &out) -> bool
auto sleep_worker(std::chrono::milliseconds wait_ms) -> void
auto protocol_to_group(const std::string &protocol) -> std::string
auto empty_object_schema() -> std::string
auto find_entity(scene &scn, const std::string &id) -> entt::handle
auto to_lower_ascii(std::string value) -> std::string
auto require_edit_scene(rtti::context &ctx, scene *&out_scene, std::string &error) -> bool
auto read_bool(const simdjson::dom::object &args, const char *key, bool &out) -> bool
auto read_double(const simdjson::dom::object &args, const char *key, double &out) -> bool
auto entity_id_string(entt::handle entity) -> std::string
void apply_pose_direct(entt::handle entity, const transform_snapshot &pose, bool is_local)
auto starts_with(std::string_view value, std::string_view prefix) -> bool
auto read_wait_ms(const simdjson::dom::object &args, int64_t default_ms=1000) -> std::chrono::milliseconds
auto read_transform_space(const simdjson::dom::object &args, bool &out_is_local, std::string &error) -> bool
Parse transform space: "world" (default) or "local". Returns false on invalid values.
auto read_string(const simdjson::dom::object &args, const char *key, std::string &out) -> bool
auto require_open_project(rtti::context &ctx, std::string &error) -> bool
auto contains_ci(std::string_view haystack, std::string_view needle) -> bool
auto normalize_asset_type_filter(std::string type) -> std::string
auto bbox_to_json(const math::bbox &bounds) -> std::string
auto read_transform_snapshot(const simdjson::dom::object &obj, transform_snapshot &out) -> void
auto entity_id_string(entt::handle entity) -> std::string
Stable id string for MCP/editor tooling (UUID preferred).
auto find_entity_by_id(scene &scn, const std::string &id) -> entt::handle
Resolve an entity by UUID string or integral entt id.
Storage for box vector values and wraps up common functionality.
auto get_active_scene(rtti::context &ctx) -> scene *
Owns play-mode state and orchestrates the splash -> running lifecycle.
static void mark_transform_global_as_changed(entt::handle entity, bool position, bool rotation, bool scale, bool skew)
static void mark_transform_as_changed(entt::handle entity, bool position, bool rotation, bool scale, bool skew)
Marks transform properties as changed in prefab override system.
Represents a scene in the ACE framework, managing entities and their relationships.