CL_Sprite::CL_Sprite(CL_GraphicContext &gc, CL_IODevice &file, const CL_String &image_type, const CL_ImageImportDescription &import_desc ) : impl(new CL_Sprite_Impl()) { CL_SpriteDescription desc; desc.add_frame(file, image_type, import_desc ); impl->create_textures(gc, desc); restart(); }
CL_Sprite::CL_Sprite(CL_GraphicContext &gc, const CL_StringRef &filename, CL_VirtualDirectory &dir, const CL_ImageImportDescription &import_desc) : impl(new CL_Sprite_Impl()) { CL_SpriteDescription desc; desc.add_frame(filename, dir, import_desc ); impl->create_textures(gc, desc); restart(); }
std::shared_ptr<TerrainWrapper> TerrainManager::createDefaultEntity(const std::string &aRelativeFilepath) { CL_SpriteDescription proxyDescription; proxyDescription.add_frame(ASSET_PATH+aRelativeFilepath); CL_Sprite proxySprite(World::instance.getGraphicWrapper().cl(), proxyDescription); proxySprite.set_alignment(origin_top_left); std::shared_ptr<Drawer> proxyDrawer = std::make_shared<DrawerSprite>(World::instance.getGraphicWrapper(), proxySprite); std::shared_ptr<Controller> controllerNull = std::make_shared<ControllerNull>(); std::shared_ptr<TerrainWrapper> proxy = std::make_shared<TerrainWrapper>(controllerNull, proxyDrawer); proxy->setDeletionHandler(std::make_shared<DeletionHandlerTerrain>()); PhysicsMaterial proxyMaterial(EPSILON, EPSILON, 10000.f, 13, 13); PhysicsSystem::addEntity(*proxy, PHYSICS_BOX); return proxy; }
CL_Sprite& Tile::get_sprite() { if (impl->sprite) { return impl->sprite; } else { if (impl->provider) { impl->sprite = impl->provider.get_sprite(); } else { CL_SpriteDescription desc; desc.add_frame(CL_PixelBuffer(get_pixelbuffer())); impl->sprite = CL_Sprite(desc); } return impl->sprite; } }
// The start of the Application int App::start(const std::vector<CL_String> &args) { quit = false; try { CL_OpenGLWindowDescription desc; desc.set_title("ClanLib AnimCursor Test"); desc.set_size(CL_Size(800, 600), true); CL_DisplayWindow window(desc); // Connect the Window close event CL_Slot slot_quit = window.sig_window_close().connect(this, &App::on_window_close); // Connect a keyboard handler to on_key_up() CL_Slot slot_input_up = (window.get_ic().get_keyboard()).sig_key_up().connect(this, &App::on_input_up); // Get the graphic context CL_GraphicContext gc = window.get_gc(); CL_Font font = CL_Font(gc, "Tahoma", 20); CL_PixelBuffer pacman("pacman.png"); CL_SpriteDescription description; CL_Size size(22, 22); for (int frame_cnt=0; frame_cnt < 6; frame_cnt++) { CL_PixelBuffer frame(size.width, size.height, cl_rgba8); pacman.convert(frame, size, CL_Rect((frame_cnt * 28) + 4, 4, size)); description.add_frame(frame); description.set_frame_delay(frame_cnt, 0.1); } CL_Point hotspot(0,0); CL_Cursor cursor(window, description, hotspot); window.set_cursor(cursor); // Run until someone presses escape while (!quit) { gc.clear(CL_Colorf(0.0f,0.0f,0.5f)); font.draw_text(gc, 32, 32, "Observe the animated cursor"); // Flip the display, showing on the screen what we have drawed // since last call to flip() window.flip(1); // This call processes user input and other events CL_KeepAlive::process(); } } catch(CL_Exception& exception) { // Create a console window for text-output if not available CL_ConsoleWindow console("Console", 80, 200); CL_Console::write_line("Exception caught:"); CL_Console::write_line(exception.message); // Display the stack trace (if available) std::vector<CL_String> stacktrace = exception.get_stack_trace(); int size = stacktrace.size(); if (size > 0) { CL_Console::write_line("Stack Trace:"); for (int cnt=0; cnt < size; cnt++) { CL_Console::write_line(stacktrace[cnt]); } } console.display_close_message(); return -1; } return 0; }
void CL_Sprite_Impl::create_textures(CL_GraphicContext &gc, const CL_SpriteDescription &description) { // Fetch frames const std::vector<CL_SpriteDescriptionFrame> &description_frames = description.get_frames(); std::vector<CL_SpriteDescriptionFrame>::const_iterator it_frames; // Calculate estimated texture group size if (texture_group.is_null()) { // *** This algorithm may not work! *** int max_width = 1; int max_height = 1; int num_objects = 0; int min_width = 9999999; int min_height = min_width; int total_width = 1; const int allowed_pixel_gap = 4; for (it_frames = description_frames.begin(); it_frames != description_frames.end(); ++it_frames) { CL_SpriteDescriptionFrame description_frame = (*it_frames); int width = description_frame.rect.get_width(); int height = description_frame.rect.get_width(); if (max_width < width) max_width = width; if (max_height < height) max_height = height; if (min_width > width) min_width = width; if (min_height > height) min_height = height; total_width += width + allowed_pixel_gap; num_objects++; } int group_width = total_width; int group_height = max_height; // Check all will fit into a single line const int max_group_size = 512; if (group_width > max_group_size) { group_width = max_group_size; group_height *= (total_width + max_group_size - 1) / max_group_size; } // Ensure power of 2 - width if (group_width > 256) group_width = 512; else if (group_width > 128) group_width = 256; else if (group_width > 64) group_width = 128; else if (group_width > 32) group_width = 64; else group_width = 32; // Ensure power of 2 - height if (group_height > 256) group_height = 512; else if (group_height > 128) group_height = 256; else if (group_height > 64) group_height = 128; else if (group_height > 32) group_height = 64; else group_height = 32; // Only create group if an object will definately fit into it if ( (group_width >= min_width) && (group_height >= min_height) && (num_objects > 1) ) { texture_group = CL_TextureGroup(CL_Size(group_width, group_height)); } } int texture_group_width; int texture_group_height; if (texture_group.is_null()) { texture_group_width = -1; texture_group_height = -1; } else { CL_Size size = texture_group.get_texture_sizes(); texture_group_width = size.width; texture_group_height = size.height; } for (it_frames = description_frames.begin(); it_frames != description_frames.end(); ++it_frames) { CL_SpriteDescriptionFrame description_frame = (*it_frames); if(description_frame.type == CL_SpriteDescriptionFrame::type_pixelbuffer) { CL_PixelBuffer image = description_frame.pixelbuffer; if (texture_group_width >0 && description_frame.rect.get_width() <= texture_group_width && description_frame.rect.get_height() <= texture_group_height) { CL_Subtexture subtexture = texture_group.add(gc, description_frame.rect.get_size()); subtexture.get_texture().set_subimage(subtexture.get_geometry().get_top_left(), image, description_frame.rect); subtexture.get_texture().set_mag_filter(linear_filter ? cl_filter_linear : cl_filter_nearest); subtexture.get_texture().set_min_filter(linear_filter ? cl_filter_linear : cl_filter_nearest); SpriteFrame frame; frame.position = subtexture.get_geometry(); frame.texture = subtexture.get_texture(); frame.delay_ms = 60; frame.offset = CL_Point(0, 0); frames.push_back(frame); } else { int width = description_frame.rect.get_width(); int height = description_frame.rect.get_height(); // Note, forced power of 2 textures have clamping issues int texture_width = width; int texture_height = height; CL_Texture texture(gc, texture_width, texture_height); texture.set_subimage(CL_Point(0,0), image, description_frame.rect); texture.set_mag_filter(linear_filter ? cl_filter_linear : cl_filter_nearest); texture.set_min_filter(linear_filter ? cl_filter_linear : cl_filter_nearest); SpriteFrame frame; frame.position = CL_Rect(0, 0, width, height); frame.texture = texture; frame.delay_ms = 60; frame.offset = CL_Point(0, 0); frames.push_back(frame); } } else if(description_frame.type == CL_SpriteDescriptionFrame::type_texture) { SpriteFrame frame; frame.position = description_frame.rect; frame.texture = description_frame.texture; frame.delay_ms = 60; frame.offset = CL_Point(0, 0); frames.push_back(frame); } } }
CL_Sprite* ManagerSprite::loadSprite( CL_GraphicContext& gc, const typelib::size2Int_t& needVisualSize, const pathSprite_t& path ) { // пробуем получить спрайт из кеша const auto ftr = mKnownSprite.find( path ); if (ftr != mKnownSprite.cend()) { return ftr->second.get(); } // собираем фреймы для спрайта // # Фреймы спрайта сгруппированы по папкам событий. #ifdef _DEBUG std::cout << "\nПодготавливаем спрайт '" << path << "'\n"; #endif std::unique_ptr< CL_Sprite > sprite; // фреймы для визуального образа CL_SpriteDescription ds; std::set< std::string > frameSet; typelib::file::listFile( &frameSet, path, "png" ); typelib::file::listFile( &frameSet, path, "jpg" ); /* - # Допустимо, что спрайта для некоторых событий нет. ASSERT( !frameSet.empty() && "Для спрайта не найдено ни одного фрейма. " " Визуальный образ не может быть собран." ); */ if ( !frameSet.empty() ) { for (auto ftr = frameSet.cbegin(); ftr != frameSet.cend(); ++ftr) { const std::string& f = *ftr; const std::string pathFrame = path + "/" + f; const auto image = frame( pathFrame ); ds.add_frame( *image ); } // сам виз. образ sprite = std::unique_ptr< CL_Sprite >( new CL_Sprite( gc, ds ) ); // @todo Конфигурируем спрайт. // начало координат для спрайта - по центру const int cx = sprite->get_width() / 2; const int cy = sprite->get_height() / 2; sprite->set_alignment( origin_center ); // задаём масштаб // # Учитываем существующий масштаб спрайта. float fixSX, fixSY; sprite->get_scale( fixSX, fixSY ); const typelib::size2_t scale( needVisualSize.x / static_cast< float >( sprite->get_width() ) * fixSX, needVisualSize.y / static_cast< float >( sprite->get_height() ) * fixSY ); sprite->set_scale( scale.x, scale.y ); sprite->update(); #ifdef _DEBUG std::cout << "Спрайт '" << path << "' собран.\n"; #endif } else { #ifdef _DEBUG std::cout << "Спрайт '" << path << "' не найден.\n"; #endif } // else if ( !frameSet.empty() ) // # Есть спрайт или нет - отметим факт загрузки. const auto ltr = mKnownSprite.insert( std::make_pair( path, std::move( sprite ) ) ).first; return ltr->second.get(); }