rects::ltrb<float> item_button::iterate_children_attachments(bool draw, std::vector<vertex_triangle>* target, augs::rgba border_col) { auto item_sprite = item->get<components::sprite>(); const auto& gui_def = resource_manager.find(item_sprite.tex)->gui_sprite_def; item_sprite.flip_horizontally = gui_def.flip_horizontally; item_sprite.flip_vertically = gui_def.flip_vertically; item_sprite.rotation_offset = gui_def.rotation_offset; item_sprite.color.a = border_col.a; shared::state_for_drawing_renderable state; state.screen_space_mode = true; state.overridden_target_buffer = target; auto expanded_size = rc.get_size() - with_attachments_bbox.get_size(); state.renderable_transform.pos = get_absolute_xy() - with_attachments_bbox.get_position() + expanded_size/2 + vec2(1, 1); rects::ltrb<float> button_bbox = item_sprite.get_aabb(components::transform(), true); if (!is_container_open) { for_each_descendant(item, [this, draw, &item_sprite, &state, &button_bbox](augs::entity_id desc) { if (desc == item) return; auto parent_slot = desc->get<components::item>().current_slot; if (parent_slot.should_item_inside_keep_physical_body(item)) { auto attachment_sprite = desc->get<components::sprite>(); attachment_sprite.flip_horizontally = item_sprite.flip_horizontally; attachment_sprite.flip_vertically = item_sprite.flip_vertically; attachment_sprite.rotation_offset = item_sprite.rotation_offset; attachment_sprite.color.a = item_sprite.color.a; shared::state_for_drawing_renderable attachment_state = state; auto offset = parent_slot.sum_attachment_offsets_of_parents(desc) - item->get<components::item>().current_slot.sum_attachment_offsets_of_parents(item); if (attachment_sprite.flip_horizontally) { offset.pos.x = -offset.pos.x; offset.flip_rotation(); } if (attachment_sprite.flip_vertically) { offset.pos.y = -offset.pos.y; offset.flip_rotation(); } offset += item_sprite.size / 2; offset += -attachment_sprite.size / 2; attachment_state.renderable_transform += offset; if (draw) attachment_sprite.draw(attachment_state); rects::ltrb<float> attachment_bbox = attachment_sprite.get_aabb(offset, true); button_bbox.contain(attachment_bbox); } }); } if(draw) item_sprite.draw(state); return button_bbox; }
void perform_transfer(const item_slot_transfer_request r, logic_step& step) { auto& cosmos = r.get_item().get_cosmos(); auto& item = r.get_item().get<components::item>(); const auto previous_slot_id = item.current_slot; const auto previous_slot = cosmos[previous_slot_id]; const auto result = query_transfer_result(r); const bool is_pickup_or_transfer = result.result == item_transfer_result_type::SUCCESSFUL_TRANSFER; const bool is_drop_request = result.result == item_transfer_result_type::SUCCESSFUL_DROP; if (result.result == item_transfer_result_type::UNMOUNT_BEFOREHAND) { ensure(false); ensure(previous_slot.alive()); //item.request_unmount(r.get_target_slot()); //item.mark_parent_enclosing_containers_for_unmount(); return; } else if (is_pickup_or_transfer || is_drop_request) { components::transform previous_container_transform; entity_id target_item_to_stack_with; if (is_pickup_or_transfer) { for (auto& i : cosmos.get_handle(r.get_target_slot())->items_inside) { if (can_stack_entities(r.get_item(), cosmos[i])) { target_item_to_stack_with = i; } } } const bool whole_item_grabbed = item.charges == result.transferred_charges; if (previous_slot.alive()) { previous_container_transform = previous_slot.get_container().logic_transform(); if (whole_item_grabbed) { remove_item(previous_slot, r.get_item()); } if (previous_slot.is_input_enabling_slot()) { unset_input_flags_of_orphaned_entity(r.get_item()); } } if (cosmos[target_item_to_stack_with].alive()) { if (whole_item_grabbed) { step.transient.messages.post(messages::queue_destruction(r.get_item())); } else { item.charges -= result.transferred_charges; } cosmos[target_item_to_stack_with].get<components::item>().charges += result.transferred_charges; return; } entity_id grabbed_item_part; if (whole_item_grabbed) { grabbed_item_part = r.get_item(); } else { grabbed_item_part = cosmos.clone_entity(r.get_item()); item.charges -= result.transferred_charges; cosmos[grabbed_item_part].get<components::item>().charges = result.transferred_charges; } const auto grabbed_item_part_handle = cosmos[grabbed_item_part]; if (is_pickup_or_transfer) { add_item(r.get_target_slot(), grabbed_item_part_handle); } auto physics_updater = [previous_container_transform](const entity_handle descendant, ...) { const auto& cosmos = descendant.get_cosmos(); const auto parent_slot = cosmos[descendant.get<components::item>().current_slot]; auto def = descendant.get<components::fixtures>().get_data(); entity_id owner_body; if (parent_slot.alive()) { def.activated = parent_slot.should_item_inside_keep_physical_body(); if (def.activated) { owner_body = parent_slot.get_root_container(); def.offsets_for_created_shapes[colliders_offset_type::ITEM_ATTACHMENT_DISPLACEMENT] = sum_attachment_offsets(cosmos, descendant.get_address_from_root()); } else { owner_body = descendant; } def.offsets_for_created_shapes[colliders_offset_type::SPECIAL_MOVE_DISPLACEMENT].reset(); } else { def.activated = true; owner_body = descendant; def.offsets_for_created_shapes[colliders_offset_type::ITEM_ATTACHMENT_DISPLACEMENT].reset(); def.offsets_for_created_shapes[colliders_offset_type::SPECIAL_MOVE_DISPLACEMENT].reset(); } descendant.get<components::fixtures>() = def; descendant.get<components::fixtures>().set_owner_body(owner_body); if (descendant.has<components::physics>()) { descendant.get<components::physics>().set_transform(previous_container_transform); if (descendant.has<components::interpolation>()) { descendant.get<components::interpolation>().place_of_birth = descendant.logic_transform(); } } }; physics_updater(grabbed_item_part_handle); grabbed_item_part_handle.for_each_contained_item_recursive(physics_updater); if (is_pickup_or_transfer) { initialize_item_button_for_new_gui_owner(grabbed_item_part_handle, inventory_traversal()); grabbed_item_part_handle.for_each_contained_slot_and_item_recursive(initialize_slot_button_for_new_gui_owner, initialize_item_button_for_new_gui_owner); } const auto previous_capability = previous_slot.get_container().get_owning_transfer_capability(); const auto target_capability = r.get_target_slot().get_container().get_owning_transfer_capability(); if (target_capability.alive() && target_capability != previous_capability) { if (target_capability.has<components::gui_element>()) { components::gui_element::assign_item_to_first_free_hotbar_button(target_capability, grabbed_item_part_handle); } } auto& grabbed_item = grabbed_item_part_handle.get<components::item>(); if (is_pickup_or_transfer) { if (r.get_target_slot()->items_need_mounting) { grabbed_item.intended_mounting = components::item::MOUNTED; if (r.force_immediate_mount) { grabbed_item.current_mounting = components::item::MOUNTED; } } } if (is_drop_request) { const auto force = vec2().set_from_degrees(previous_container_transform.rotation).set_length(60); const auto offset = vec2().random_on_circle(20, cosmos.get_rng_for(r.get_item())); auto& physics = grabbed_item_part_handle.get<components::physics>(); physics.apply_force(force, offset, true); auto& special_physics = grabbed_item_part_handle.get<components::special_physics>(); special_physics.since_dropped.set(200, cosmos.get_timestamp()); } } }