GUIChatConsole::GUIChatConsole( gui::IGUIEnvironment* env, gui::IGUIElement* parent, s32 id, ChatBackend* backend, Client* client, IMenuManager* menumgr ): IGUIElement(gui::EGUIET_ELEMENT, env, parent, id, core::rect<s32>(0,0,100,100)), m_chat_backend(backend), m_client(client), m_menumgr(menumgr), m_animate_time_old(porting::getTimeMs()) { // load background settings s32 console_alpha = g_settings->getS32("console_alpha"); m_background_color.setAlpha(clamp_u8(console_alpha)); // load the background texture depending on settings ITextureSource *tsrc = client->getTextureSource(); if (tsrc->isKnownSourceImage("background_chat.jpg")) { m_background = tsrc->getTexture("background_chat.jpg"); m_background_color.setRed(255); m_background_color.setGreen(255); m_background_color.setBlue(255); } else { v3f console_color = g_settings->getV3F("console_color"); m_background_color.setRed(clamp_u8(myround(console_color.X))); m_background_color.setGreen(clamp_u8(myround(console_color.Y))); m_background_color.setBlue(clamp_u8(myround(console_color.Z))); } m_font = g_fontengine->getFont(FONT_SIZE_UNSPECIFIED, FM_Mono); if (!m_font) { errorstream << "GUIChatConsole: Unable to load mono font "; } else { core::dimension2d<u32> dim = m_font->getDimension(L"M"); m_fontsize = v2u32(dim.Width, dim.Height); m_font->grab(); } m_fontsize.X = MYMAX(m_fontsize.X, 1); m_fontsize.Y = MYMAX(m_fontsize.Y, 1); // set default cursor options setCursor(true, true, 2.0, 0.1); }
bool MapBlockMesh::animate(bool faraway, float time, int crack, u32 daynight_ratio) { bool enable_shaders = g_settings->getBool("enable_shaders"); bool enable_bumpmapping = g_settings->getBool("enable_bumpmapping"); bool enable_parallax_occlusion = g_settings->getBool("enable_parallax_occlusion"); if(!m_has_animation) { m_animation_force_timer = 100000; return false; } m_animation_force_timer = myrand_range(5, 100); // Cracks if(crack != m_last_crack) { for(std::map<u32, std::string>::iterator i = m_crack_materials.begin(); i != m_crack_materials.end(); i++) { scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first); std::string basename = i->second; // Create new texture name from original ITextureSource *tsrc = m_gamedef->getTextureSource(); std::ostringstream os; os<<basename<<crack; u32 new_texture_id = 0; video::ITexture *new_texture = tsrc->getTexture(os.str(), &new_texture_id); buf->getMaterial().setTexture(0, new_texture); // If the current material is also animated, // update animation info std::map<u32, TileSpec>::iterator anim_iter = m_animation_tiles.find(i->first); if(anim_iter != m_animation_tiles.end()){ TileSpec &tile = anim_iter->second; tile.texture = new_texture; tile.texture_id = new_texture_id; // force animation update m_animation_frames[i->first] = -1; } } m_last_crack = crack; } // Texture animation for(std::map<u32, TileSpec>::iterator i = m_animation_tiles.begin(); i != m_animation_tiles.end(); i++) { const TileSpec &tile = i->second; // Figure out current frame int frameoffset = m_animation_frame_offsets[i->first]; int frame = (int)(time * 1000 / tile.animation_frame_length_ms + frameoffset) % tile.animation_frame_count; // If frame doesn't change, skip if(frame == m_animation_frames[i->first]) continue; m_animation_frames[i->first] = frame; scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first); ITextureSource *tsrc = m_gamedef->getTextureSource(); // Create new texture name from original std::ostringstream os(std::ios::binary); os<<tsrc->getTextureName(tile.texture_id); os<<"^[verticalframe:"<<(int)tile.animation_frame_count<<":"<<frame; // Set the texture buf->getMaterial().setTexture(0, tsrc->getTexture(os.str())); buf->getMaterial().setTexture(2, tsrc->getTexture("disable_img.png")); if (enable_shaders && (enable_bumpmapping || enable_parallax_occlusion)) { std::string fname_base,fname_normal; fname_base = tsrc->getTextureName(tile.texture_id); unsigned pos; pos = fname_base.find("."); fname_normal = fname_base.substr (0, pos); fname_normal += "_normal.png"; if (tsrc->isKnownSourceImage(fname_normal)){ os.str(""); os<<fname_normal<<"^[verticalframe:"<<(int)tile.animation_frame_count<<":"<<frame; buf->getMaterial().setTexture(1, tsrc->getTexture(os.str())); buf->getMaterial().setTexture(2, tsrc->getTexture("enable_img.png")); } } } // Day-night transition if(daynight_ratio != m_last_daynight_ratio) { for(std::map<u32, std::map<u32, std::pair<u8, u8> > >::iterator i = m_daynight_diffs.begin(); i != m_daynight_diffs.end(); i++) { scene::IMeshBuffer *buf = m_mesh->getMeshBuffer(i->first); video::S3DVertex *vertices = (video::S3DVertex*)buf->getVertices(); for(std::map<u32, std::pair<u8, u8 > >::iterator j = i->second.begin(); j != i->second.end(); j++) { u32 vertexIndex = j->first; u8 day = j->second.first; u8 night = j->second.second; finalColorBlend(vertices[vertexIndex].Color, day, night, daynight_ratio); // Brighten topside (no shaders) if(vertices[vertexIndex].Normal.Y > 0.5) { video::SColor &vc = vertices[vertexIndex].Color; vc.setRed (srgb_linear_multiply(vc.getRed(), 1.3, 255.0)); vc.setGreen(srgb_linear_multiply(vc.getGreen(), 1.3, 255.0)); vc.setBlue (srgb_linear_multiply(vc.getBlue(), 1.3, 255.0)); } } } m_last_daynight_ratio = daynight_ratio; } return true; }
MapBlockMesh::MapBlockMesh(MeshMakeData *data, v3s16 camera_offset): m_mesh(new scene::SMesh()), m_gamedef(data->m_gamedef), m_animation_force_timer(0), // force initial animation m_last_crack(-1), m_crack_materials(), m_last_daynight_ratio((u32) -1), m_daynight_diffs() { // 4-21ms for MAP_BLOCKSIZE=16 (NOTE: probably outdated) // 24-155ms for MAP_BLOCKSIZE=32 (NOTE: probably outdated) //TimeTaker timer1("MapBlockMesh()"); std::vector<FastFace> fastfaces_new; /* We are including the faces of the trailing edges of the block. This means that when something changes, the caller must also update the meshes of the blocks at the leading edges. NOTE: This is the slowest part of this method. */ { // 4-23ms for MAP_BLOCKSIZE=16 (NOTE: probably outdated) //TimeTaker timer2("updateAllFastFaceRows()"); updateAllFastFaceRows(data, fastfaces_new); } // End of slow part /* Convert FastFaces to MeshCollector */ MeshCollector collector; { // avg 0ms (100ms spikes when loading textures the first time) // (NOTE: probably outdated) //TimeTaker timer2("MeshCollector building"); for(u32 i=0; i<fastfaces_new.size(); i++) { FastFace &f = fastfaces_new[i]; const u16 indices[] = {0,1,2,2,3,0}; const u16 indices_alternate[] = {0,1,3,2,3,1}; if(f.tile.texture == NULL) continue; const u16 *indices_p = indices; /* Revert triangles for nicer looking gradient if vertices 1 and 3 have same color or 0 and 2 have different color. getRed() is the day color. */ if(f.vertices[0].Color.getRed() != f.vertices[2].Color.getRed() || f.vertices[1].Color.getRed() == f.vertices[3].Color.getRed()) indices_p = indices_alternate; collector.append(f.tile, f.vertices, 4, indices_p, 6); } } /* Add special graphics: - torches - flowing water - fences - whatever */ mapblock_mesh_generate_special(data, collector); /* Convert MeshCollector to SMesh */ bool enable_shaders = g_settings->getBool("enable_shaders"); bool enable_bumpmapping = g_settings->getBool("enable_bumpmapping"); bool enable_parallax_occlusion = g_settings->getBool("enable_parallax_occlusion"); video::E_MATERIAL_TYPE shadermat1, shadermat2, shadermat3, shadermat4, shadermat5; shadermat1 = shadermat2 = shadermat3 = shadermat4 = shadermat5 = video::EMT_SOLID; if (enable_shaders) { IShaderSource *shdrsrc = m_gamedef->getShaderSource(); shadermat1 = shdrsrc->getShader("solids_shader").material; shadermat2 = shdrsrc->getShader("liquids_shader").material; shadermat3 = shdrsrc->getShader("alpha_shader").material; shadermat4 = shdrsrc->getShader("leaves_shader").material; shadermat5 = shdrsrc->getShader("plants_shader").material; } for(u32 i = 0; i < collector.prebuffers.size(); i++) { PreMeshBuffer &p = collector.prebuffers[i]; /*dstream<<"p.vertices.size()="<<p.vertices.size() <<", p.indices.size()="<<p.indices.size() <<std::endl;*/ // Generate animation data // - Cracks if(p.tile.material_flags & MATERIAL_FLAG_CRACK) { ITextureSource *tsrc = data->m_gamedef->tsrc(); // Find the texture name plus ^[crack:N: std::ostringstream os(std::ios::binary); os<<tsrc->getTextureName(p.tile.texture_id)<<"^[crack"; if(p.tile.material_flags & MATERIAL_FLAG_CRACK_OVERLAY) os<<"o"; // use ^[cracko os<<":"<<(u32)p.tile.animation_frame_count<<":"; m_crack_materials.insert(std::make_pair(i, os.str())); // Replace tile texture with the cracked one p.tile.texture = tsrc->getTexture( os.str()+"0", &p.tile.texture_id); } // - Texture animation if(p.tile.material_flags & MATERIAL_FLAG_ANIMATION_VERTICAL_FRAMES) { ITextureSource *tsrc = data->m_gamedef->tsrc(); // Add to MapBlockMesh in order to animate these tiles m_animation_tiles[i] = p.tile; m_animation_frames[i] = 0; if(g_settings->getBool("desynchronize_mapblock_texture_animation")){ // Get starting position from noise m_animation_frame_offsets[i] = 100000 * (2.0 + noise3d( data->m_blockpos.X, data->m_blockpos.Y, data->m_blockpos.Z, 0)); } else { // Play all synchronized m_animation_frame_offsets[i] = 0; } // Replace tile texture with the first animation frame std::ostringstream os(std::ios::binary); os<<tsrc->getTextureName(p.tile.texture_id); os<<"^[verticalframe:"<<(int)p.tile.animation_frame_count<<":0"; p.tile.texture = tsrc->getTexture( os.str(), &p.tile.texture_id); } // - Classic lighting (shaders handle this by themselves) if(!enable_shaders) { for(u32 j = 0; j < p.vertices.size(); j++) { video::SColor &vc = p.vertices[j].Color; // Set initial real color and store for later updates u8 day = vc.getRed(); u8 night = vc.getGreen(); finalColorBlend(vc, day, night, 1000); if(day != night) m_daynight_diffs[i][j] = std::make_pair(day, night); // Brighten topside (no shaders) if(p.vertices[j].Normal.Y > 0.5) { vc.setRed (srgb_linear_multiply(vc.getRed(), 1.3, 255.0)); vc.setGreen(srgb_linear_multiply(vc.getGreen(), 1.3, 255.0)); vc.setBlue (srgb_linear_multiply(vc.getBlue(), 1.3, 255.0)); } } } // Create material video::SMaterial material; material.setFlag(video::EMF_LIGHTING, false); material.setFlag(video::EMF_BACK_FACE_CULLING, true); material.setFlag(video::EMF_BILINEAR_FILTER, false); material.setFlag(video::EMF_FOG_ENABLE, true); //material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_OFF); //material.setFlag(video::EMF_ANTI_ALIASING, video::EAAM_SIMPLE); //material.MaterialType = video::EMT_TRANSPARENT_ALPHA_CHANNEL_REF; material.setTexture(0, p.tile.texture); if (enable_shaders) { ITextureSource *tsrc = data->m_gamedef->tsrc(); material.setTexture(2, tsrc->getTexture("disable_img.png")); if (enable_bumpmapping || enable_parallax_occlusion) { std::string fname_base = tsrc->getTextureName(p.tile.texture_id); std::string normal_ext = "_normal.png"; size_t pos = fname_base.find("."); std::string fname_normal = fname_base.substr(0, pos) + normal_ext; if (tsrc->isKnownSourceImage(fname_normal)) { // look for image extension and replace it size_t i = 0; while ((i = fname_base.find(".", i)) != std::string::npos) { fname_base.replace(i, 4, normal_ext); i += normal_ext.length(); } material.setTexture(1, tsrc->getTexture(fname_base)); material.setTexture(2, tsrc->getTexture("enable_img.png")); } } p.tile.applyMaterialOptionsWithShaders(material, shadermat1, shadermat2, shadermat3, shadermat4, shadermat5); } else { p.tile.applyMaterialOptions(material); } // Create meshbuffer // This is a "Standard MeshBuffer", // it's a typedeffed CMeshBuffer<video::S3DVertex> scene::SMeshBuffer *buf = new scene::SMeshBuffer(); // Set material buf->Material = material; // Add to mesh m_mesh->addMeshBuffer(buf); // Mesh grabbed it buf->drop(); buf->append(&p.vertices[0], p.vertices.size(), &p.indices[0], p.indices.size()); } m_camera_offset = camera_offset; /* Do some stuff to the mesh */ translateMesh(m_mesh, intToFloat(data->m_blockpos * MAP_BLOCKSIZE - camera_offset, BS)); if(m_mesh) { #if 0 // Usually 1-700 faces and 1-7 materials std::cout<<"Updated MapBlock has "<<fastfaces_new.size()<<" faces " <<"and uses "<<m_mesh->getMeshBufferCount() <<" materials (meshbuffers)"<<std::endl; #endif // Use VBO for mesh (this just would set this for ever buffer) // This will lead to infinite memory usage because or irrlicht. //m_mesh->setHardwareMappingHint(scene::EHM_STATIC); /* NOTE: If that is enabled, some kind of a queue to the main thread should be made which would call irrlicht to delete the hardware buffer and then delete the mesh */ } //std::cout<<"added "<<fastfaces.getSize()<<" faces."<<std::endl; // Check if animation is required for this mesh m_has_animation = !m_crack_materials.empty() || !m_daynight_diffs.empty() || !m_animation_tiles.empty(); }