/* ExternalEditManager::monitorStopped * Called when a FileMonitor is stopped/deleted *******************************************************************/ void ExternalEditManager::monitorStopped(ExternalEditFileMonitor* monitor) { if (VECTOR_EXISTS(file_monitors, monitor)) VECTOR_REMOVE(file_monitors, monitor); }
/* MapObjectPropsPanel::openObject * Populates the grid with properties for all MapObjects in [objects] *******************************************************************/ void MapObjectPropsPanel::openObjects(vector<MapObject*>& objects) { // Check any objects were given if (objects.size() == 0 || objects[0] == NULL) { this->objects.clear(); pg_properties->DisableProperty(pg_properties->GetGrid()->GetRoot()); pg_properties->SetPropertyValueUnspecified(pg_properties->GetGrid()->GetRoot()); pg_properties->Refresh(); pg_props_side1->DisableProperty(pg_props_side1->GetGrid()->GetRoot()); pg_props_side1->SetPropertyValueUnspecified(pg_props_side1->GetGrid()->GetRoot()); pg_props_side1->Refresh(); pg_props_side2->DisableProperty(pg_props_side2->GetGrid()->GetRoot()); pg_props_side2->SetPropertyValueUnspecified(pg_props_side2->GetGrid()->GetRoot()); pg_props_side2->Refresh(); return; } else pg_properties->EnableProperty(pg_properties->GetGrid()->GetRoot()); // Setup property grid for the object type if (theMapEditor->currentMapDesc().format == MAP_UDMF) setupTypeUDMF(objects[0]->getObjType()); else setupType(objects[0]->getObjType()); // Find any custom properties (UDMF only) if (theMapEditor->currentMapDesc().format == MAP_UDMF) { for (unsigned a = 0; a < objects.size(); a++) { // Go through object properties vector<MobjPropertyList::prop_t> objprops = objects[a]->props().allProperties(); for (unsigned b = 0; b < objprops.size(); b++) { // Ignore side property if (objprops[b].name.StartsWith("side1.") || objprops[b].name.StartsWith("side2.")) continue; // Check if hidden if (VECTOR_EXISTS(hide_props, objprops[b].name)) continue; // Check if property is already on the list bool exists = false; for (unsigned c = 0; c < properties.size(); c++) { if (properties[c]->getPropName() == objprops[b].name) { exists = true; break; } } if (!exists) { // Create custom group if needed if (!group_custom) group_custom = pg_properties->Append(new wxPropertyCategory("Custom")); //LOG_MESSAGE(2, "Add custom property \"%s\"", objprops[b].name); // Add property switch (objprops[b].value.getType()) { case PROP_BOOL: addBoolProperty(group_custom, objprops[b].name, objprops[b].name); break; case PROP_INT: addIntProperty(group_custom, objprops[b].name, objprops[b].name); break; case PROP_FLOAT: addFloatProperty(group_custom, objprops[b].name, objprops[b].name); break; default: addStringProperty(group_custom, objprops[b].name, objprops[b].name); break; } } } } } // Generic properties for (unsigned a = 0; a < properties.size(); a++) properties[a]->openObjects(objects); // Handle line sides if (objects[0]->getObjType() == MOBJ_LINE) { // Enable/disable side properties wxPGProperty* prop = pg_properties->GetProperty("sidefront"); if (prop && (prop->IsValueUnspecified() || prop->GetValue().GetInteger() >= 0)) pg_props_side1->EnableProperty(pg_props_side1->GetGrid()->GetRoot()); else { pg_props_side1->DisableProperty(pg_props_side1->GetGrid()->GetRoot()); pg_props_side1->SetPropertyValueUnspecified(pg_props_side1->GetGrid()->GetRoot()); } prop = pg_properties->GetProperty("sideback"); if (prop && (prop->IsValueUnspecified() || prop->GetValue().GetInteger() >= 0)) pg_props_side2->EnableProperty(pg_props_side2->GetGrid()->GetRoot()); else { pg_props_side2->DisableProperty(pg_props_side2->GetGrid()->GetRoot()); pg_props_side2->SetPropertyValueUnspecified(pg_props_side2->GetGrid()->GetRoot()); } } // Update internal objects list if (&objects != &this->objects) { this->objects.clear(); for (unsigned a = 0; a < objects.size(); a++) this->objects.push_back(objects[a]); } // Possibly update the argument names and visibility updateArgs(NULL); pg_properties->Refresh(); pg_props_side1->Refresh(); pg_props_side2->Refresh(); }
/* WadArchive::open * Reads wad format data from a MemChunk * Returns true if successful, false otherwise *******************************************************************/ bool WadArchive::open(MemChunk& mc) { // Check data was given if (!mc.hasData()) return false; // Read wad header uint32_t num_lumps = 0; uint32_t dir_offset = 0; char wad_type[4] = ""; mc.seek(0, SEEK_SET); mc.read(&wad_type, 4); // Wad type mc.read(&num_lumps, 4); // No. of lumps in wad mc.read(&dir_offset, 4); // Offset to directory // Byteswap values for big endian if needed num_lumps = wxINT32_SWAP_ON_BE(num_lumps); dir_offset = wxINT32_SWAP_ON_BE(dir_offset); // Check the header if (wad_type[1] != 'W' || wad_type[2] != 'A' || wad_type[3] != 'D') { wxLogMessage("WadArchive::openFile: File %s has invalid header", filename); Global::error = "Invalid wad header"; return false; } // Check for iwad if (wad_type[0] == 'I') iwad = true; // Stop announcements (don't want to be announcing modification due to entries being added etc) setMuted(true); vector<uint32_t> offsets; // Read the directory mc.seek(dir_offset, SEEK_SET); theSplashWindow->setProgressMessage("Reading wad archive data"); for (uint32_t d = 0; d < num_lumps; d++) { // Update splash window progress theSplashWindow->setProgress(((float)d / (float)num_lumps)); // Read lump info char name[9] = ""; uint32_t offset = 0; uint32_t size = 0; mc.read(&offset, 4); // Offset mc.read(&size, 4); // Size mc.read(name, 8); // Name name[8] = '\0'; // Byteswap values for big endian if needed offset = wxINT32_SWAP_ON_BE(offset); size = wxINT32_SWAP_ON_BE(size); // Check to catch stupid shit if (size > 0) { if (offset == 0) { LOG_MESSAGE(2, "No."); continue; } if (VECTOR_EXISTS(offsets, offset)) { LOG_MESSAGE(1, "Ignoring entry %d: %s, is a clone of a previous entry", d, name); continue; } offsets.push_back(offset); } // Hack to open Operation: Rheingold WAD files if (size == 0 && offset > mc.getSize()) offset = 0; // Is there a compression/encryption thing going on? bool jaguarencrypt = !!(name[0] & 0x80); // look at high bit name[0] = name[0] & 0x7F; // then strip it away // Look for encryption shenanigans size_t actualsize = size; if (jaguarencrypt) { if (d < num_lumps - 1) { size_t pos = mc.currentPos(); uint32_t nextoffset = 0; for (int i = 0; i + d < num_lumps; ++i) { mc.read(&nextoffset, 4); if (nextoffset != 0) break; mc.seek(12, SEEK_CUR); } nextoffset = wxINT32_SWAP_ON_BE(nextoffset); if (nextoffset == 0) nextoffset = dir_offset; mc.seek(pos, SEEK_SET); actualsize = nextoffset - offset; } else { if (offset > dir_offset) { actualsize = mc.getSize() - offset; } else { actualsize = dir_offset - offset; } } } // If the lump data goes past the end of the file, // the wadfile is invalid if (offset + actualsize > mc.getSize()) { wxLogMessage("WadArchive::open: Wad archive is invalid or corrupt"); Global::error = S_FMT("Archive is invalid and/or corrupt (lump %d: %s data goes past end of file)", d, name); setMuted(false); return false; } // Create & setup lump ArchiveEntry* nlump = new ArchiveEntry(wxString::FromAscii(name), size); nlump->setLoaded(false); nlump->exProp("Offset") = (int)offset; nlump->setState(0); if (jaguarencrypt) { nlump->setEncryption(ENC_JAGUAR); nlump->exProp("FullSize") = (int)size; } // Add to entry list getRoot()->addEntry(nlump); } // Detect namespaces (needs to be done before type detection as some types // rely on being within certain namespaces) updateNamespaces(); // Detect all entry types MemChunk edata; theSplashWindow->setProgressMessage("Detecting entry types"); for (size_t a = 0; a < numEntries(); a++) { // Update splash window progress theSplashWindow->setProgress((((float)a / (float)numEntries()))); // Get entry ArchiveEntry* entry = getEntry(a); // Read entry data if it isn't zero-sized if (entry->getSize() > 0) { // Read the entry data mc.exportMemChunk(edata, getEntryOffset(entry), entry->getSize()); if (entry->isEncrypted()) { if (entry->exProps().propertyExists("FullSize") && (unsigned)(int)(entry->exProp("FullSize")) > entry->getSize()) edata.reSize((int)(entry->exProp("FullSize")), true); if (!JaguarDecode(edata)) wxLogMessage("%i: %s (following %s), did not decode properly", a, entry->getName(), a>0?getEntry(a-1)->getName():"nothing"); } entry->importMemChunk(edata); } // Detect entry type EntryType::detectEntryType(entry); // Unload entry data if needed if (!archive_load_data) entry->unloadData(); // Set entry to unchanged entry->setState(0); } // Identify #included lumps (DECORATE, GLDEFS, etc.) detectIncludes(); // Detect maps (will detect map entry types) theSplashWindow->setProgressMessage("Detecting maps"); detectMaps(); // Setup variables setMuted(false); setModified(false); //if (iwad && iwad_lock) read_only = true; announce("opened"); theSplashWindow->setProgressMessage(""); return true; }
/* MapObjectPropsPanel::setupTypeUDMF * Adds all relevant UDMF properties to the grid for [objtype] *******************************************************************/ void MapObjectPropsPanel::setupTypeUDMF(int objtype) { // Nothing to do if it was already this type if (last_type == objtype) return; // Clear property grids clearGrid(); // Hide buttons if not needed if (no_apply || mobj_props_auto_apply) { btn_apply->Show(false); btn_reset->Show(false); } else if (!no_apply) { btn_apply->Show(); btn_reset->Show(); } // Set main tab title if (objtype == MOBJ_VERTEX) stc_sections->SetPageText(0, "Vertex"); else if (objtype == MOBJ_LINE) stc_sections->SetPageText(0, "Line"); else if (objtype == MOBJ_SECTOR) stc_sections->SetPageText(0, "Sector"); else if (objtype == MOBJ_THING) stc_sections->SetPageText(0, "Thing"); // Go through all possible properties for this type vector<udmfp_t> props = theGameConfiguration->allUDMFProperties(objtype); sort(props.begin(), props.end()); for (unsigned a = 0; a < props.size(); a++) { // Skip if hidden if ((hide_flags && props[a].property->isFlag()) || (hide_triggers && props[a].property->isTrigger())) { hide_props.push_back(props[a].property->getProperty()); continue; } if (VECTOR_EXISTS(hide_props, props[a].property->getProperty())) continue; addUDMFProperty(props[a].property, objtype); } // Add side properties if line type if (objtype == MOBJ_LINE) { // Add side tabs pg_props_side1->Show(true); pg_props_side2->Show(true); stc_sections->AddPage(pg_props_side1, "Front Side"); stc_sections->AddPage(pg_props_side2, "Back Side"); // Get side properties vector<udmfp_t> sprops = theGameConfiguration->allUDMFProperties(MOBJ_SIDE); sort(sprops.begin(), sprops.end()); // Front side for (unsigned a = 0; a < sprops.size(); a++) { // Skip if hidden if ((hide_flags && sprops[a].property->isFlag()) || (hide_triggers && sprops[a].property->isTrigger())) { hide_props.push_back(sprops[a].property->getProperty()); continue; } if (VECTOR_EXISTS(hide_props, sprops[a].property->getProperty())) continue; addUDMFProperty(sprops[a].property, objtype, "side1", pg_props_side1); } // Back side for (unsigned a = 0; a < sprops.size(); a++) { // Skip if hidden if ((hide_flags && sprops[a].property->isFlag()) || (hide_triggers && sprops[a].property->isTrigger())) { hide_props.push_back(sprops[a].property->getProperty()); continue; } if (VECTOR_EXISTS(hide_props, sprops[a].property->getProperty())) continue; addUDMFProperty(sprops[a].property, objtype, "side2", pg_props_side2); } } // Set all bool properties to use checkboxes pg_properties->SetPropertyAttributeAll(wxPG_BOOL_USE_CHECKBOX, true); // Remember arg properties for passing to type/special properties (or set // to NULL if args don't exist) for (unsigned arg = 0; arg < 5; arg++) args[arg] = pg_properties->GetProperty(S_FMT("arg%u", arg)); last_type = objtype; Layout(); }