void importEditorImages(MapTexHashMap& map, ArchiveTreeNode* dir, string path) { SImage image; // Go through entries for (unsigned a = 0; a < dir->numEntries(); a++) { ArchiveEntry* entry = dir->getEntry(a); // Load entry to image if (image.open(entry->getMCData())) { // Create texture in hashmap string name = path + entry->getName(true); //wxLogMessage("Loading editor texture %s", CHR(name)); map_tex_t& mtex = map[name]; mtex.texture = new GLTexture(false); mtex.texture->setFilter(GLTexture::MIPMAP); mtex.texture->loadImage(&image); } } // Go through subdirs for (unsigned a = 0; a < dir->nChildren(); a++) { ArchiveTreeNode* subdir = (ArchiveTreeNode*)dir->getChild(a); importEditorImages(map, subdir, path + subdir->getName() + "/"); } }
void updateEntry() { // Read file MemChunk data; data.importFile(filename); // Read image SImage image; image.open(data, 0, "png"); image.convertPaletted(&palette); // Convert image to entry gfx format SIFormat* format = SIFormat::getFormat(gfx_format); if (format) { MemChunk conv_data; if (format->saveImage(image, conv_data, &palette)) { // Update entry data entry->importMemChunk(conv_data); EntryOperations::setGfxOffsets(entry, offsets.x, offsets.y); } else { LOG_MESSAGE(1, "Unable to convert external png to %s", format->getName()); } } }
/* CTexture::parseDefine * Parses a HIRESTEX define block *******************************************************************/ bool CTexture::parseDefine(Tokenizer& tz) { this->type = "Define"; this->extended = true; this->defined = true; name = tz.getToken().Upper(); def_width = tz.getInteger(); def_height = tz.getInteger(); width = def_width; height = def_height; ArchiveEntry* entry = theResourceManager->getPatchEntry(name); if (entry) { SImage image; if (image.open(entry->getMCData())) { width = image.getWidth(); height = image.getHeight(); scale_x = (double)width / (double)def_width; scale_y = (double)height / (double)def_height; } } CTPatchEx* patch = new CTPatchEx(name); patches.push_back(patch); return true; }
// ----------------------------------------------------------------------------- // Loads all editor images (thing icons, etc) from the program resource archive // ----------------------------------------------------------------------------- void MapTextureManager::importEditorImages(MapTexHashMap& map, ArchiveTreeNode* dir, std::string_view path) const { SImage image; // Go through entries for (unsigned a = 0; a < dir->numEntries(); a++) { auto entry = dir->entryAt(a); // Load entry to image if (image.open(entry->data())) { // Create texture in hashmap auto name = fmt::format("{}{}", path, entry->nameNoExt()); Log::info(4, "Loading editor texture {}", name); auto& mtex = map[name]; mtex.gl_id = OpenGL::Texture::createFromImage(image, nullptr, OpenGL::TexFilter::Mipmap); } } // Go through subdirs for (unsigned a = 0; a < dir->nChildren(); a++) { auto subdir = dynamic_cast<ArchiveTreeNode*>(dir->child(a)); importEditorImages(map, subdir, fmt::format("{}{}/", path, subdir->name())); } }
// ----------------------------------------------------------------------------- // Search for errors in texture list, return true if any are found // ----------------------------------------------------------------------------- bool TextureXList::findErrors() { bool ret = false; // Texture errors: // 1. A texture without any patch // 2. A texture with missing patches // 3. A texture with columns not covered by a patch for (unsigned a = 0; a < textures_.size(); a++) { if (textures_[a]->nPatches() == 0) { ret = true; Log::warning("Texture {}: {} does not have any patch", a, textures_[a]->name()); } else { vector<uint8_t> columns(textures_[a]->width()); memset(columns.data(), 0, textures_[a]->width()); for (size_t i = 0; i < textures_[a]->nPatches(); ++i) { auto patch = textures_[a]->patches_[i]->patchEntry(); if (patch == nullptr) { ret = true; Log::warning( "Texture {}: {}: patch {} cannot be found in any open archive", a, textures_[a]->name(), textures_[a]->patches_[i]->name()); // Don't list missing columns when we don't know the size of the patch memset(columns.data(), 1, textures_[a]->width()); } else { SImage img; img.open(patch->data()); size_t start = std::max<size_t>(0, textures_[a]->patches_[i]->xOffset()); size_t end = std::min<size_t>(textures_[a]->width(), img.width() + start); for (size_t c = start; c < end; ++c) columns[c] = 1; } } for (size_t c = 0; c < textures_[a]->width(); ++c) { if (columns[c] == 0) { ret = true; Log::warning("Texture {}: {}: column {} without a patch", a, textures_[a]->name(), c); break; } } } } return ret; }
/* MapPreviewCanvas::draw * Draws the map *******************************************************************/ void MapPreviewCanvas::draw() { // Setup colours rgba_t col_view_background = ColourConfiguration::getColour("map_view_background"); rgba_t col_view_line_1s = ColourConfiguration::getColour("map_view_line_1s"); rgba_t col_view_line_2s = ColourConfiguration::getColour("map_view_line_2s"); rgba_t col_view_line_special = ColourConfiguration::getColour("map_view_line_special"); rgba_t col_view_line_macro = ColourConfiguration::getColour("map_view_line_macro"); rgba_t col_view_thing = ColourConfiguration::getColour("map_view_thing"); // Setup the viewport glViewport(0, 0, GetSize().x, GetSize().y); // Setup the screen projection glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, GetSize().x, 0, GetSize().y, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Clear glClearColor(((double)col_view_background.r)/255.f, ((double)col_view_background.g)/255.f, ((double)col_view_background.b)/255.f, ((double)col_view_background.a)/255.f); glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT); // Translate to inside of pixel (otherwise inaccuracies can occur on certain gl implementations) if (OpenGL::accuracyTweak()) glTranslatef(0.375f, 0.375f, 0); // Zoom/offset to show full map showMap(); // Translate to middle of canvas glTranslated(GetSize().x * 0.5, GetSize().y * 0.5, 0); // Zoom glScaled(zoom, zoom, 1); // Translate to offset glTranslated(-offset_x, -offset_y, 0); // Setup drawing glDisable(GL_TEXTURE_2D); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glLineWidth(1.5f); glEnable(GL_LINE_SMOOTH); // Draw lines for (unsigned a = 0; a < lines.size(); a++) { mep_line_t line = lines[a]; // Check ends if (line.v1 >= verts.size() || line.v2 >= verts.size()) continue; // Get vertices mep_vertex_t v1 = verts[lines[a].v1]; mep_vertex_t v2 = verts[lines[a].v2]; // Set colour if (line.special) OpenGL::setColour(col_view_line_special); else if (line.macro) OpenGL::setColour(col_view_line_macro); else if (line.twosided) OpenGL::setColour(col_view_line_2s); else OpenGL::setColour(col_view_line_1s); // Draw line glBegin(GL_LINES); glVertex2d(v1.x, v1.y); glVertex2d(v2.x, v2.y); glEnd(); } // Load thing texture if needed if (!tex_loaded) { // Load thing texture SImage image; ArchiveEntry* entry = theArchiveManager->programResourceArchive()->entryAtPath("images/thing/normal_n.png"); if (entry) { image.open(entry->getMCData()); tex_thing = new GLTexture(false); tex_thing->setFilter(GLTexture::MIPMAP); tex_thing->loadImage(&image); } else tex_thing = NULL; tex_loaded = true; } // Draw things if (map_view_things) { OpenGL::setColour(col_view_thing); if (tex_thing) { double radius = 20; glEnable(GL_TEXTURE_2D); tex_thing->bind(); for (unsigned a = 0; a < things.size(); a++) { glPushMatrix(); glTranslated(things[a].x, things[a].y, 0); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2d(-radius, -radius); glTexCoord2f(0.0f, 1.0f); glVertex2d(-radius, radius); glTexCoord2f(1.0f, 1.0f); glVertex2d(radius, radius); glTexCoord2f(1.0f, 0.0f); glVertex2d(radius, -radius); glEnd(); glPopMatrix(); } } else { glEnable(GL_POINT_SMOOTH); glPointSize(8.0f); glBegin(GL_POINTS); for (unsigned a = 0; a < things.size(); a++) glVertex2d(things[a].x, things[a].y); glEnd(); } } glLineWidth(1.0f); glDisable(GL_LINE_SMOOTH); // Swap buffers (ie show what was drawn) SwapBuffers(); }
// ----------------------------------------------------------------------------- // Draws the map // ----------------------------------------------------------------------------- void MapPreviewCanvas::draw() { // Setup colours auto col_view_background = ColourConfiguration::colour("map_view_background"); auto col_view_line_1s = ColourConfiguration::colour("map_view_line_1s"); auto col_view_line_2s = ColourConfiguration::colour("map_view_line_2s"); auto col_view_line_special = ColourConfiguration::colour("map_view_line_special"); auto col_view_line_macro = ColourConfiguration::colour("map_view_line_macro"); auto col_view_thing = ColourConfiguration::colour("map_view_thing"); // Setup the viewport glViewport(0, 0, GetSize().x, GetSize().y); // Setup the screen projection glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0, GetSize().x, 0, GetSize().y, -1, 1); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); // Clear glClearColor( ((double)col_view_background.r) / 255.f, ((double)col_view_background.g) / 255.f, ((double)col_view_background.b) / 255.f, ((double)col_view_background.a) / 255.f); glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Translate to inside of pixel (otherwise inaccuracies can occur on certain gl implementations) if (OpenGL::accuracyTweak()) glTranslatef(0.375f, 0.375f, 0); // Zoom/offset to show full map showMap(); // Translate to middle of canvas glTranslated(GetSize().x * 0.5, GetSize().y * 0.5, 0); // Zoom glScaled(zoom_, zoom_, 1); // Translate to offset glTranslated(-offset_.x, -offset_.y, 0); // Setup drawing glDisable(GL_TEXTURE_2D); glColor4f(1.0f, 1.0f, 1.0f, 1.0f); glLineWidth(1.5f); glEnable(GL_LINE_SMOOTH); // Draw lines for (auto& line : lines_) { // Check ends if (line.v1 >= verts_.size() || line.v2 >= verts_.size()) continue; // Get vertices auto v1 = verts_[line.v1]; auto v2 = verts_[line.v2]; // Set colour if (line.special) OpenGL::setColour(col_view_line_special); else if (line.macro) OpenGL::setColour(col_view_line_macro); else if (line.twosided) OpenGL::setColour(col_view_line_2s); else OpenGL::setColour(col_view_line_1s); // Draw line glBegin(GL_LINES); glVertex2d(v1.x, v1.y); glVertex2d(v2.x, v2.y); glEnd(); } // Load thing texture if needed if (!tex_loaded_) { // Load thing texture SImage image; auto entry = App::archiveManager().programResourceArchive()->entryAtPath("images/thing/normal_n.png"); if (entry) { image.open(entry->data()); tex_thing_ = OpenGL::Texture::createFromImage(image, nullptr, OpenGL::TexFilter::Mipmap); } else tex_thing_ = 0; tex_loaded_ = true; } // Draw things if (map_view_things) { OpenGL::setColour(col_view_thing); if (tex_thing_) { double radius = 20; glEnable(GL_TEXTURE_2D); OpenGL::Texture::bind(tex_thing_); for (auto& thing : things_) { glPushMatrix(); glTranslated(thing.x, thing.y, 0); glBegin(GL_QUADS); glTexCoord2f(0.0f, 0.0f); glVertex2d(-radius, -radius); glTexCoord2f(0.0f, 1.0f); glVertex2d(-radius, radius); glTexCoord2f(1.0f, 1.0f); glVertex2d(radius, radius); glTexCoord2f(1.0f, 0.0f); glVertex2d(radius, -radius); glEnd(); glPopMatrix(); } } else { glEnable(GL_POINT_SMOOTH); glPointSize(8.0f); glBegin(GL_POINTS); for (auto& thing : things_) glVertex2d(thing.x, thing.y); glEnd(); } } glLineWidth(1.0f); glDisable(GL_LINE_SMOOTH); // Swap buffers (ie show what was drawn) SwapBuffers(); }