/* ThingPropsPanel::onSpriteClicked * Called when the thing type sprite canvas is clicked *******************************************************************/ void ThingPropsPanel::onSpriteClicked(wxMouseEvent& e) { ThingTypeBrowser browser(this, type_current); if (browser.ShowModal() == wxID_OK) { // Get selected type type_current = browser.getSelectedType(); ThingType* tt = theGameConfiguration->thingType(type_current); // Update sprite gfx_sprite->setSprite(tt); label_type->SetLabel(tt->getName()); // Update args if (panel_args) { argspec_t as = tt->getArgspec(); panel_args->setup(&as, (theMapEditor->currentMapDesc().format == MAP_UDMF)); } // Update layout Layout(); Refresh(); } }
wxString MOPGThingTypeProperty::ValueToString(wxVariant &value, int argFlags) const { // Get value as integer int type = value.GetInteger(); ThingType* tt = theGameConfiguration->thingType(type); return S_FMT("%d: %s", type, CHR(tt->getName())); }
void Creature::updateWalkAnimation(int totalPixelsWalked) { // update outfit animation if(m_outfit.getCategory() != ThingCategoryCreature) return; int footAnimPhases = getAnimationPhases() - 1; int footDelay = getStepDuration(true) / 3; // Since mount is a different outfit we need to get the mount animation phases if(m_outfit.getMount() != 0) { ThingType *type = g_things.rawGetThingType(m_outfit.getMount(), m_outfit.getCategory()); footAnimPhases = type->getAnimationPhases() - 1; } if(footAnimPhases == 0) m_walkAnimationPhase = 0; else if(m_footStepDrawn && m_footTimer.ticksElapsed() >= footDelay && totalPixelsWalked < 32) { m_footStep++; m_walkAnimationPhase = 1 + (m_footStep % footAnimPhases); m_footStepDrawn = false; m_footTimer.restart(); } else if(m_walkAnimationPhase == 0 && totalPixelsWalked < 32) { m_walkAnimationPhase = 1 + (m_footStep % footAnimPhases); } if(totalPixelsWalked == 32 && !m_walkFinishAnimEvent) { auto self = static_self_cast<Creature>(); m_walkFinishAnimEvent = g_dispatcher.scheduleEvent([self] { if(!self->m_walking || self->m_walkTimer.ticksElapsed() >= self->getStepDuration(true)) self->m_walkAnimationPhase = 0; self->m_walkFinishAnimEvent = nullptr; }, std::min<int>(footDelay, 200)); } }
virtual void doCheck() { for (unsigned a = 0; a < map->nThings(); a++) { ThingType* tt = theGameConfiguration->thingType(map->getThing(a)->getType()); if (tt->getName() == "Unknown") things.push_back(map->getThing(a)); } }
void doCheck() { double radius; // Get list of lines to check vector<MapLine*> check_lines; MapLine* line; for (unsigned a = 0; a < map->nLines(); a++) { line = map->getLine(a); // Skip if line is 2-sided and not blocking if (line->s2() && !theGameConfiguration->lineBasicFlagSet("blocking", line, map->currentFormat())) continue; check_lines.push_back(line); } // Go through things for (unsigned a = 0; a < map->nThings(); a++) { MapThing* thing = map->getThing(a); ThingType* tt = theGameConfiguration->thingType(thing->getType()); // Skip if not a solid thing if (!tt->isSolid()) continue; radius = tt->getRadius() - 1; // Go through lines for (unsigned b = 0; b < check_lines.size(); b++) { line = check_lines[b]; // Check intersection if (MathStuff::boxLineIntersect(thing->xPos() - radius, thing->yPos() - radius, thing->xPos() + radius, thing->yPos() + radius, line->x1(), line->y1(), line->x2(), line->y2())) { things.push_back(thing); lines.push_back(line); break; } } } }
void MOPGThingTypeProperty::openObjects(vector<MapObject*>& objects) { // Reset arg property names for (unsigned a = 0; a < 5; a++) { if (args[a]) { args[a]->SetLabel(S_FMT("Arg%d", a+1)); args[a]->SetHelpString(""); } } // Set unspecified if no objects given if (objects.size() == 0) { SetValueToUnspecified(); return; } // Get property of first object int first = objects[0]->intProperty(GetName()); // Check whether all objects share the same value for (unsigned a = 1; a < objects.size(); a++) { if (objects[a]->intProperty(GetName()) != first) { // Different value found, set unspecified SetValueToUnspecified(); return; } } // Set to common value noupdate = true; if (!parent->showAll() && udmf_prop && !udmf_prop->showAlways() && udmf_prop->getDefaultValue().getIntValue() == first) Hide(true); else Hide(false); SetValue(first); noupdate = false; // Set arg property names ThingType* tt = theGameConfiguration->thingType(first); for (unsigned a = 0; a < 5; a++) { if (!args[a]) continue; args[a]->SetLabel(tt->getArg(a).name); args[a]->SetHelpString(tt->getArg(a).desc); } }
/* ThingPropsPanel::openObjects * Loads values from things in [objects] *******************************************************************/ void ThingPropsPanel::openObjects(vector<MapObject*>& objects) { if (objects.empty()) return; int map_format = theMapEditor->currentMapDesc().format; int ival; double fval; // Load flags if (map_format == MAP_UDMF) { bool val = false; for (unsigned a = 0; a < udmf_flags.size(); a++) { if (MapObject::multiBoolProperty(objects, udmf_flags[a], val)) cb_flags[a]->SetValue(val); else cb_flags[a]->Set3StateValue(wxCHK_UNDETERMINED); } } else { for (int a = 0; a < theGameConfiguration->nThingFlags(); a++) { // Set initial flag checked value cb_flags[a]->SetValue(theGameConfiguration->thingFlagSet(a, (MapThing*)objects[0])); // Go through subsequent things for (unsigned b = 1; b < objects.size(); b++) { // Check for mismatch if (cb_flags[a]->GetValue() != theGameConfiguration->thingFlagSet(a, (MapThing*)objects[b])) { // Set undefined cb_flags[a]->Set3StateValue(wxCHK_UNDETERMINED); break; } } } } // Type type_current = 0; if (MapObject::multiIntProperty(objects, "type", type_current)) { ThingType* tt = theGameConfiguration->thingType(type_current); gfx_sprite->setSprite(tt); label_type->SetLabel(S_FMT("%d: %s", type_current, tt->getName())); label_type->Wrap(136); } // Special ival = -1; if (panel_special) { if (MapObject::multiIntProperty(objects, "special", ival)) panel_special->setSpecial(ival); } // Args if (map_format == MAP_HEXEN || map_format == MAP_UDMF) { // Setup if (ival > 0) { argspec_t as = theGameConfiguration->actionSpecial(ival)->getArgspec(); panel_args->setup(&as, (map_format == MAP_UDMF)); } else { argspec_t as = theGameConfiguration->thingType(type_current)->getArgspec(); panel_args->setup(&as, (map_format == MAP_UDMF)); } // Load values int args[5] = { -1, -1, -1, -1, -1 }; for (unsigned a = 0; a < 5; a++) MapObject::multiIntProperty(objects, S_FMT("arg%d", a), args[a]); panel_args->setValues(args); } // Direction if (MapObject::multiIntProperty(objects, "angle", ival)) ac_direction->setAngle(ival); // Id if (map_format != MAP_DOOM && MapObject::multiIntProperty(objects, "id", ival)) text_id->setNumber(ival); // Z Height if (map_format == MAP_HEXEN && MapObject::multiIntProperty(objects, "height", ival)) text_height->setNumber(ival); else if (map_format == MAP_UDMF && MapObject::multiFloatProperty(objects, "height", fval)) text_height->setDecNumber(fval); // Load other properties mopp_other_props->openObjects(objects); // Update internal objects list this->objects.clear(); for (unsigned a = 0; a < objects.size(); a++) this->objects.push_back(objects[a]); // Update layout Layout(); Refresh(); }
void Creature::internalDrawOutfit(Point dest, float scaleFactor, bool animateWalk, bool animateIdle, Otc::Direction direction) { // outfit is a real creature if(m_outfit.getCategory() == ThingCategoryCreature) { int animationPhase = animateWalk ? m_walkAnimationPhase : 0; if(isAnimateAlways() && animateIdle) { int ticksPerFrame = 1000 / getAnimationPhases(); animationPhase = (g_clock.millis() % (ticksPerFrame * getAnimationPhases())) / ticksPerFrame; } // xPattern => creature direction int xPattern; if(direction == Otc::NorthEast || direction == Otc::SouthEast) xPattern = Otc::East; else if(direction == Otc::NorthWest || direction == Otc::SouthWest) xPattern = Otc::West; else xPattern = direction; int zPattern = 0; if(m_outfit.getMount() != 0) { auto datType = g_things.rawGetThingType(m_outfit.getMount(), ThingCategoryCreature); dest -= datType->getDisplacement() * scaleFactor; datType->draw(dest, scaleFactor, 0, xPattern, 0, 0, animationPhase); dest += getDisplacement() * scaleFactor; zPattern = 1; } // yPattern => creature addon for(int yPattern = 0; yPattern < getNumPatternY(); yPattern++) { // continue if we dont have this addon if(yPattern > 0 && !(m_outfit.getAddons() & (1 << (yPattern-1)))) continue; auto datType = rawGetThingType(); datType->draw(dest, scaleFactor, 0, xPattern, yPattern, zPattern, animationPhase); if(getLayers() > 1) { Color oldColor = g_painter->getColor(); Painter::CompositionMode oldComposition = g_painter->getCompositionMode(); g_painter->setCompositionMode(Painter::CompositionMode_Multiply); g_painter->setColor(m_outfit.getHeadColor()); datType->draw(dest, scaleFactor, SpriteMaskYellow, xPattern, yPattern, zPattern, animationPhase); g_painter->setColor(m_outfit.getBodyColor()); datType->draw(dest, scaleFactor, SpriteMaskRed, xPattern, yPattern, zPattern, animationPhase); g_painter->setColor(m_outfit.getLegsColor()); datType->draw(dest, scaleFactor, SpriteMaskGreen, xPattern, yPattern, zPattern, animationPhase); g_painter->setColor(m_outfit.getFeetColor()); datType->draw(dest, scaleFactor, SpriteMaskBlue, xPattern, yPattern, zPattern, animationPhase); g_painter->setColor(oldColor); g_painter->setCompositionMode(oldComposition); } } // outfit is a creature imitating an item or the invisible effect } else { ThingType *type = g_things.rawGetThingType(m_outfit.getAuxId(), m_outfit.getCategory()); int animationPhase = 0; int animationPhases = type->getAnimationPhases(); int animateTicks = Otc::ITEM_TICKS_PER_FRAME; // when creature is an effect we cant render the first and last animation phase, // instead we should loop in the phases between if(m_outfit.getCategory() == ThingCategoryEffect) { animationPhases = std::max(1, animationPhases-2); animateTicks = Otc::INVISIBLE_TICKS_PER_FRAME; } if(animationPhases > 1) { if(animateIdle) animationPhase = (g_clock.millis() % (animateTicks * animationPhases)) / animateTicks; else animationPhase = animationPhases-1; } if(m_outfit.getCategory() == ThingCategoryEffect) animationPhase = std::min(animationPhase+1, animationPhases); type->draw(dest - (getDisplacement() * scaleFactor), scaleFactor, 0, 0, 0, 0, animationPhase); } }
/* InfoOverlay3D::update * Updates the info text for the object of [item_type] at [item_index] * in [map] *******************************************************************/ void InfoOverlay3D::update(int item_index, int item_type, SLADEMap* map) { // Clear current info info.clear(); info2.clear(); // Setup variables current_type = item_type; texname = ""; texture = NULL; thing_icon = false; int map_format = theMapEditor->currentMapDesc().format; // Wall if (item_type == MapEditor::SEL_SIDE_BOTTOM || item_type == MapEditor::SEL_SIDE_MIDDLE || item_type == MapEditor::SEL_SIDE_TOP) { // Get line and side MapSide* side = map->getSide(item_index); if (!side) return; MapLine* line = side->getParentLine(); if (!line) return; object = side; // --- Line/side info --- info.push_back(S_FMT("Line #%d", line->getIndex())); if (side == line->s1()) info.push_back(S_FMT("Front Side #%d", side->getIndex())); else info.push_back(S_FMT("Back Side #%d", side->getIndex())); // Relevant flags string flags = ""; if (theGameConfiguration->lineBasicFlagSet("dontpegtop", line, map_format)) flags += "Upper Unpegged, "; if (theGameConfiguration->lineBasicFlagSet("dontpegbottom", line, map_format)) flags += "Lower Unpegged, "; if (theGameConfiguration->lineBasicFlagSet("blocking", line, map_format)) flags += "Blocking, "; if (!flags.IsEmpty()) flags.RemoveLast(2); info.push_back(flags); info.push_back(S_FMT("Length: %d", (int)line->getLength())); // Other potential info: special, sector# // --- Wall part info --- // Part if (item_type == MapEditor::SEL_SIDE_BOTTOM) info2.push_back("Lower Texture"); else if (item_type == MapEditor::SEL_SIDE_MIDDLE) info2.push_back("Middle Texture"); else info2.push_back("Upper Texture"); // Offsets if (theGameConfiguration->udmfNamespace() == "zdoom") { // Get x offset info int xoff = side->intProperty("offsetx"); double xoff_part = 0; if (item_type == MapEditor::SEL_SIDE_BOTTOM) xoff_part = side->floatProperty("offsetx_bottom"); else if (item_type == MapEditor::SEL_SIDE_MIDDLE) xoff_part = side->floatProperty("offsetx_mid"); else xoff_part = side->floatProperty("offsetx_top"); // Add x offset string string xoff_info; if (xoff_part == 0) xoff_info = S_FMT("%d", xoff); else if (xoff_part > 0) xoff_info = S_FMT("%1.2f (%d+%1.2f)", (double)xoff+xoff_part, xoff, xoff_part); else xoff_info = S_FMT("%1.2f (%d-%1.2f)", (double)xoff+xoff_part, xoff, -xoff_part); // Get y offset info int yoff = side->intProperty("offsety"); double yoff_part = 0; if (item_type == MapEditor::SEL_SIDE_BOTTOM) yoff_part = side->floatProperty("offsety_bottom"); else if (item_type == MapEditor::SEL_SIDE_MIDDLE) yoff_part = side->floatProperty("offsety_mid"); else yoff_part = side->floatProperty("offsety_top"); // Add y offset string string yoff_info; if (yoff_part == 0) yoff_info = S_FMT("%d", yoff); else if (yoff_part > 0) yoff_info = S_FMT("%1.2f (%d+%1.2f)", (double)yoff+yoff_part, yoff, yoff_part); else yoff_info = S_FMT("%1.2f (%d-%1.2f)", (double)yoff+yoff_part, yoff, -yoff_part); info2.push_back(S_FMT("Offsets: %s, %s", xoff_info, yoff_info)); } else { // Basic offsets info2.push_back(S_FMT("Offsets: %d, %d", side->intProperty("offsetx"), side->intProperty("offsety"))); } // ZDoom UDMF extras if (theGameConfiguration->udmfNamespace() == "zdoom") { // Scale double xscale, yscale; if (item_type == MapEditor::SEL_SIDE_BOTTOM) { xscale = side->floatProperty("scalex_bottom"); yscale = side->floatProperty("scaley_bottom"); } else if (item_type == MapEditor::SEL_SIDE_MIDDLE) { xscale = side->floatProperty("scalex_mid"); yscale = side->floatProperty("scaley_mid"); } else { xscale = side->floatProperty("scalex_top"); yscale = side->floatProperty("scaley_top"); } info2.push_back(S_FMT("Scale: %1.2fx, %1.2fx", xscale, yscale)); } else { info2.push_back(""); } // Height of this section of the wall // TODO this is wrong in the case of slopes, but slope support only // exists in the 3.1.1 branch fpoint2_t left_point, right_point; MapSide* other_side; if (side == line->s1()) { left_point = line->v1()->getPoint(0); right_point = line->v2()->getPoint(0); other_side = line->s2(); } else { left_point = line->v2()->getPoint(0); right_point = line->v1()->getPoint(0); other_side = line->s1(); } MapSector* this_sector = side->getSector(); MapSector* other_sector = NULL; if (other_side) other_sector = other_side->getSector(); double left_height, right_height; if (item_type == MapEditor::SEL_SIDE_MIDDLE && other_sector) { // A two-sided line's middle area is the smallest distance between // both sides' floors and ceilings, which is more complicated with // slopes. plane_t floor1 = this_sector->getFloorPlane(); plane_t floor2 = other_sector->getFloorPlane(); plane_t ceiling1 = this_sector->getCeilingPlane(); plane_t ceiling2 = other_sector->getCeilingPlane(); left_height = min(ceiling1.height_at(left_point), ceiling2.height_at(left_point)) - max(floor1.height_at(left_point), floor2.height_at(left_point)); right_height = min(ceiling1.height_at(right_point), ceiling2.height_at(right_point)) - max(floor1.height_at(right_point), floor2.height_at(right_point)); } else { plane_t top_plane, bottom_plane; if (item_type == MapEditor::SEL_SIDE_MIDDLE) { top_plane = this_sector->getCeilingPlane(); bottom_plane = this_sector->getFloorPlane(); } else { if (!other_sector) return; if (item_type == MapEditor::SEL_SIDE_TOP) { top_plane = this_sector->getCeilingPlane(); bottom_plane = other_sector->getCeilingPlane(); } else { top_plane = other_sector->getFloorPlane(); bottom_plane = this_sector->getFloorPlane(); } } left_height = top_plane.height_at(left_point) - bottom_plane.height_at(left_point); right_height = top_plane.height_at(right_point) - bottom_plane.height_at(right_point); } if (fabs(left_height - right_height) < 0.001) info2.push_back(S_FMT("Height: %d", (int)left_height)); else info2.push_back(S_FMT("Height: %d ~ %d", (int)left_height, (int)right_height)); // Texture if (item_type == MapEditor::SEL_SIDE_BOTTOM) texname = side->getTexLower(); else if (item_type == MapEditor::SEL_SIDE_MIDDLE) texname = side->getTexMiddle(); else texname = side->getTexUpper(); texture = theMapEditor->textureManager().getTexture(texname, theGameConfiguration->mixTexFlats()); } // Floor else if (item_type == MapEditor::SEL_FLOOR || item_type == MapEditor::SEL_CEILING) { // Get sector MapSector* sector = map->getSector(item_index); if (!sector) return; object = sector; // Get basic info int fheight = sector->intProperty("heightfloor"); int cheight = sector->intProperty("heightceiling"); // --- Sector info --- // Sector index info.push_back(S_FMT("Sector #%d", item_index)); // Sector height info.push_back(S_FMT("Total Height: %d", cheight - fheight)); // ZDoom UDMF extras /* if (theGameConfiguration->udmfNamespace() == "zdoom") { // Sector colour rgba_t col = sector->getColour(0, true); info.push_back(S_FMT("Colour: R%d, G%d, B%d", col.r, col.g, col.b)); } */ // --- Flat info --- // Height if (item_type == MapEditor::SEL_FLOOR) info2.push_back(S_FMT("Floor Height: %d", fheight)); else info2.push_back(S_FMT("Ceiling Height: %d", cheight)); // Light int light = sector->intProperty("lightlevel"); if (theGameConfiguration->udmfNamespace() == "zdoom") { // Get extra light info int fl = 0; bool abs = false; if (item_type == MapEditor::SEL_FLOOR) { fl = sector->intProperty("lightfloor"); abs = sector->boolProperty("lightfloorabsolute"); } else { fl = sector->intProperty("lightceiling"); abs = sector->boolProperty("lightceilingabsolute"); } // Set if absolute if (abs) { light = fl; fl = 0; } // Add info string if (fl == 0) info2.push_back(S_FMT("Light: %d", light)); else if (fl > 0) info2.push_back(S_FMT("Light: %d (%d+%d)", light+fl, light, fl)); else info2.push_back(S_FMT("Light: %d (%d-%d)", light+fl, light, -fl)); } else info2.push_back(S_FMT("Light: %d", light)); // ZDoom UDMF extras if (theGameConfiguration->udmfNamespace() == "zdoom") { // Offsets double xoff, yoff; if (item_type == MapEditor::SEL_FLOOR) { xoff = sector->floatProperty("xpanningfloor"); yoff = sector->floatProperty("ypanningfloor"); } else { xoff = sector->floatProperty("xpanningceiling"); yoff = sector->floatProperty("ypanningceiling"); } info2.push_back(S_FMT("Offsets: %1.2f, %1.2f", xoff, yoff)); // Scaling double xscale, yscale; if (item_type == MapEditor::SEL_FLOOR) { xscale = sector->floatProperty("xscalefloor"); yscale = sector->floatProperty("yscalefloor"); } else { xscale = sector->floatProperty("xscaleceiling"); yscale = sector->floatProperty("yscaleceiling"); } info2.push_back(S_FMT("Scale: %1.2fx, %1.2fx", xscale, yscale)); } // Texture if (item_type == MapEditor::SEL_FLOOR) texname = sector->getFloorTex(); else texname = sector->getCeilingTex(); texture = theMapEditor->textureManager().getFlat(texname, theGameConfiguration->mixTexFlats()); } // Thing else if (item_type == MapEditor::SEL_THING) { // index, type, position, sector, zpos, height?, radius? // Get thing MapThing* thing = map->getThing(item_index); if (!thing) return; object = thing; // Index info.push_back(S_FMT("Thing #%d", item_index)); // Position if (theMapEditor->currentMapDesc().format == MAP_HEXEN || theMapEditor->currentMapDesc().format == MAP_UDMF) info.push_back(S_FMT("Position: %d, %d, %d", (int)thing->xPos(), (int)thing->yPos(), (int)thing->floatProperty("height"))); else info.push_back(S_FMT("Position: %d, %d", (int)thing->xPos(), (int)thing->yPos())); // Type ThingType* tt = theGameConfiguration->thingType(thing->getType()); if (tt->getName() == "Unknown") info2.push_back(S_FMT("Type: %d", thing->getType())); else info2.push_back(S_FMT("Type: %s", tt->getName())); // Args if (theMapEditor->currentMapDesc().format == MAP_HEXEN || (theMapEditor->currentMapDesc().format == MAP_UDMF && theGameConfiguration->getUDMFProperty("arg0", MOBJ_THING))) { // Get thing args int args[5]; args[0] = thing->intProperty("arg0"); args[1] = thing->intProperty("arg1"); args[2] = thing->intProperty("arg2"); args[3] = thing->intProperty("arg3"); args[4] = thing->intProperty("arg4"); string argstr = tt->getArgsString(args); if (argstr.IsEmpty()) info2.push_back("No Args"); else info2.push_back(argstr); } // Sector int sector = map->sectorAt(thing->point()); if (sector >= 0) info2.push_back(S_FMT("In Sector #%d", sector)); else info2.push_back("No Sector"); // Texture texture = theMapEditor->textureManager().getSprite(tt->getSprite(), tt->getTranslation(), tt->getPalette()); if (!texture) { if (use_zeth_icons && tt->getZeth() >= 0) texture = theMapEditor->textureManager().getEditorImage(S_FMT("zethicons/zeth%02d", tt->getZeth())); if (!texture) texture = theMapEditor->textureManager().getEditorImage(S_FMT("thing/%s", tt->getIcon())); thing_icon = true; } texname = ""; } last_update = theApp->runTimer(); }
/* MOPGThingTypeProperty::getArgspec * Returns a little object describing the args for this thing type *******************************************************************/ const argspec_t MOPGThingTypeProperty::getArgspec() { int type = m_value.GetInteger(); ThingType* tt = theGameConfiguration->thingType(type); return tt->getArgspec(); }