void Entity::addToRender(SceneRenderer &out, Color color) const { //PROFILE("Entity::addToRender"); IRect rect = m_sprite.getRect(m_seq_idx, m_frame_idx, m_dir_idx); if(!areOverlapping(out.targetRect(), rect + (int2)worldToScreen(m_pos))) return; FBox bbox = boundingBox() - pos(); if(shrinkRenderedBBox() && bbox.height() >= 2.0f) bbox = {float3(bbox.x(), min(bbox.y() + 1.0f, bbox.ey() - 0.5f), bbox.z()), bbox.max()}; bool as_overlay = renderAsOverlay(); FRect tex_rect; auto tex = m_sprite.getFrame(m_seq_idx, m_frame_idx, m_dir_idx, tex_rect); bool added = out.add(tex, rect, m_pos, bbox, color, tex_rect, as_overlay); if(added && m_oseq_idx != -1 && m_oframe_idx != -1) { //TODO: overlay may be visible, while normal sprite is not! rect = m_sprite.getRect(m_oseq_idx, m_oframe_idx, m_dir_idx); auto ov_tex = m_sprite.getFrame(m_oseq_idx, m_oframe_idx, m_dir_idx, tex_rect); out.add(ov_tex, rect, m_pos, bbox, color, tex_rect, true); } // if(findAny(boundingBox(), {Flags::all | Flags::colliding, ref()})) // out.addBox(bbox + pos(), ColorId::red); }
bool World::findClosestPos(int3 &out, const int3 &source, const IBox &target_box, EntityRef agent_ref) const { const Entity *agent = const_cast<World*>(this)->refEntity(agent_ref); if(agent) { FBox bbox = agent->boundingBox(); const NaviMap *navi_map = naviMap(bbox); if(navi_map) return navi_map->findClosestPos(out, source, bbox.height(), target_box); } return false; }
void WorldViewer::update(double time_diff) { FWK_PROFILE("WorldViewer::update"); Actor *spectator = m_world->refEntity<Actor>(m_spectator); if((int)m_entities.size() != m_world->entityCount()) m_entities.resize(m_world->entityCount()); if(!m_spectator) { for(int n = 0; n < (int)m_entities.size(); n++) { Entity *entity = m_world->refEntity(n); VisEntity &vis_entity = m_entities[n]; vis_entity.ref = entity? entity->ref() : EntityRef(); vis_entity.mode = entity? VisEntity::visible : VisEntity::invisible; vis_entity.occluder_id = -1; } return; } if(!spectator) return; FBox bbox = spectator->boundingBox(); m_cur_pos = bbox.center(); m_eye_pos = asXZY(m_cur_pos.xz(), bbox.min.y + bbox.height() * 0.75f); for(int n = 0; n < (int)m_entities.size(); n++) { Entity *entity = m_world->refEntity(n); VisEntity &vis_entity = m_entities[n]; if(!entity) { vis_entity = VisEntity(); continue; } const auto *desc = m_world->refEntityDesc(n); DASSERT(desc); bool is_visible = m_see_all || spectator == entity || spectator->canSee(entity->ref(), !isMovable(*entity)); if(vis_entity.ref != entity->ref()) { vis_entity = VisEntity(); vis_entity.ref = entity->ref(); vis_entity.mode = is_visible? VisEntity::visible : VisEntity::invisible; } if(is_visible) { vis_entity.occluder_id = desc->occluder_id; if(vis_entity.mode == VisEntity::visible) continue; if(vis_entity.mode == VisEntity::shadowed || vis_entity.mode == VisEntity::pre_blending_out) { vis_entity.shadow.reset(); vis_entity.mode = VisEntity::visible; } else { float blend_value = 0.0; if(vis_entity.mode == VisEntity::blending_in) blend_value = vis_entity.blend_value; else if(vis_entity.mode == VisEntity::blending_out) blend_value = blend_time - vis_entity.blend_value; blend_value += time_diff; vis_entity.mode = blend_value > blend_time? VisEntity::visible : VisEntity::blending_in; vis_entity.blend_value = blend_value; } } else { if(vis_entity.mode == VisEntity::shadowed || vis_entity.mode == VisEntity::invisible) continue; if(vis_entity.mode == VisEntity::visible) { vis_entity.blend_value = 0.0f; vis_entity.mode = VisEntity::pre_blending_out; } if(vis_entity.mode == VisEntity::pre_blending_out) { vis_entity.blend_value += time_diff; if(vis_entity.blend_value > blend_time) { if(isMovable(*entity)) { vis_entity.mode = VisEntity::blending_out; vis_entity.blend_value = vis_entity.blend_value - blend_time; } else { vis_entity.mode = VisEntity::shadowed; vis_entity.occluder_id = desc->occluder_id; vis_entity.shadow.reset(entity->clone()); } } } else { float blend_value = 0.0f; if(vis_entity.mode == VisEntity::blending_in) blend_value = blend_time - vis_entity.blend_value; else if(vis_entity.mode == VisEntity::blending_out) blend_value = vis_entity.blend_value; vis_entity.blend_value = blend_value + time_diff; vis_entity.mode = VisEntity::blending_out; if(vis_entity.blend_value > blend_time) vis_entity.mode = VisEntity::invisible; } } } if(m_occluder_config.update(spectator->boundingBox())) m_world->tileMap().updateVisibility(m_occluder_config); }