mirror of
https://thingvellir.net/git/overte
synced 2025-03-27 23:52:03 +01:00
commit
18613908df
12 changed files with 138 additions and 9 deletions
|
@ -424,7 +424,14 @@ void MyAvatar::simulate(float deltaTime) {
|
|||
EntityTreeRenderer* entityTreeRenderer = qApp->getEntities();
|
||||
EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr;
|
||||
if (entityTree) {
|
||||
bool flyingAllowed = true;
|
||||
bool ghostingAllowed = true;
|
||||
entityTree->withWriteLock([&] {
|
||||
std::shared_ptr<ZoneEntityItem> zone = entityTreeRenderer->myAvatarZone();
|
||||
if (zone) {
|
||||
flyingAllowed = zone->getFlyingAllowed();
|
||||
ghostingAllowed = zone->getGhostingAllowed();
|
||||
}
|
||||
auto now = usecTimestampNow();
|
||||
EntityEditPacketSender* packetSender = qApp->getEntityEditPacketSender();
|
||||
MovingEntitiesOperator moveOperator(entityTree);
|
||||
|
@ -452,6 +459,10 @@ void MyAvatar::simulate(float deltaTime) {
|
|||
entityTree->recurseTreeWithOperator(&moveOperator);
|
||||
}
|
||||
});
|
||||
_characterController.setFlyingAllowed(flyingAllowed);
|
||||
if (!_characterController.isEnabled() && !ghostingAllowed) {
|
||||
_characterController.setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1788,7 +1799,21 @@ void MyAvatar::updateMotionBehaviorFromMenu() {
|
|||
} else {
|
||||
_motionBehaviors &= ~AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED;
|
||||
}
|
||||
_characterController.setEnabled(menu->isOptionChecked(MenuOption::EnableCharacterController));
|
||||
|
||||
bool ghostingAllowed = true;
|
||||
EntityTreeRenderer* entityTreeRenderer = qApp->getEntities();
|
||||
if (entityTreeRenderer) {
|
||||
std::shared_ptr<ZoneEntityItem> zone = entityTreeRenderer->myAvatarZone();
|
||||
if (zone) {
|
||||
ghostingAllowed = zone->getGhostingAllowed();
|
||||
}
|
||||
}
|
||||
bool checked = menu->isOptionChecked(MenuOption::EnableCharacterController);
|
||||
if (!ghostingAllowed) {
|
||||
checked = true;
|
||||
}
|
||||
|
||||
_characterController.setEnabled(checked);
|
||||
}
|
||||
|
||||
void MyAvatar::clearDriveKeys() {
|
||||
|
|
|
@ -88,6 +88,8 @@ public:
|
|||
// For Scene.shouldRenderEntities
|
||||
QList<EntityItemID>& getEntitiesLastInScene() { return _entityIDsLastInScene; }
|
||||
|
||||
std::shared_ptr<ZoneEntityItem> myAvatarZone() { return _bestZone; }
|
||||
|
||||
signals:
|
||||
void mousePressOnEntity(const RayToEntityIntersectionResult& intersection, const QMouseEvent* event);
|
||||
void mousePressOffEntity(const RayToEntityIntersectionResult& intersection, const QMouseEvent* event);
|
||||
|
|
|
@ -307,6 +307,8 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_QUERY_AA_CUBE, queryAACube);
|
||||
CHECK_PROPERTY_CHANGE(PROP_LOCAL_POSITION, localPosition);
|
||||
CHECK_PROPERTY_CHANGE(PROP_LOCAL_ROTATION, localRotation);
|
||||
CHECK_PROPERTY_CHANGE(PROP_FLYING_ALLOWED, flyingAllowed);
|
||||
CHECK_PROPERTY_CHANGE(PROP_GHOSTING_ALLOWED, ghostingAllowed);
|
||||
|
||||
changedProperties += _animation.getChangedProperties();
|
||||
changedProperties += _keyLight.getChangedProperties();
|
||||
|
@ -465,6 +467,9 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
|
||||
_stage.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
|
||||
_skybox.copyToScriptValue(_desiredProperties, properties, engine, skipDefaults, defaultEntityProperties);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_FLYING_ALLOWED, flyingAllowed);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_GHOSTING_ALLOWED, ghostingAllowed);
|
||||
}
|
||||
|
||||
// Web only
|
||||
|
@ -675,6 +680,9 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(jointTranslationsSet, qVectorBool, setJointTranslationsSet);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(jointTranslations, qVectorVec3, setJointTranslations);
|
||||
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(flyingAllowed, bool, setFlyingAllowed);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(ghostingAllowed, bool, setGhostingAllowed);
|
||||
|
||||
_lastEdited = usecTimestampNow();
|
||||
}
|
||||
|
||||
|
@ -845,6 +853,9 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
|
|||
ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_HOUR, Stage, stage, Hour, hour);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_AUTOMATIC_HOURDAY, Stage, stage, AutomaticHourDay, automaticHourDay);
|
||||
|
||||
ADD_PROPERTY_TO_MAP(PROP_FLYING_ALLOWED, FlyingAllowed, flyingAllowed, bool);
|
||||
ADD_PROPERTY_TO_MAP(PROP_GHOSTING_ALLOWED, GhostingAllowed, ghostingAllowed, bool);
|
||||
|
||||
// FIXME - these are not yet handled
|
||||
//ADD_PROPERTY_TO_MAP(PROP_CREATED, Created, created, quint64);
|
||||
|
||||
|
@ -1085,6 +1096,9 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
|
||||
_staticSkybox.setProperties(properties);
|
||||
_staticSkybox.appendToEditPacket(packetData, requestedProperties, propertyFlags, propertiesDidntFit, propertyCount, appendState);
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_FLYING_ALLOWED, properties.getFlyingAllowed());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GHOSTING_ALLOWED, properties.getGhostingAllowed());
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::PolyVox) {
|
||||
|
@ -1369,6 +1383,9 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, QString, setCompoundShapeURL);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_BACKGROUND_MODE, BackgroundMode, setBackgroundMode);
|
||||
properties.getSkybox().decodeFromEditPacket(propertyFlags, dataAt , processedBytes);
|
||||
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_FLYING_ALLOWED, bool, setFlyingAllowed);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_GHOSTING_ALLOWED, bool, setGhostingAllowed);
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::PolyVox) {
|
||||
|
@ -1559,6 +1576,9 @@ void EntityItemProperties::markAllChanged() {
|
|||
_jointTranslationsChanged = true;
|
||||
|
||||
_queryAACubeChanged = true;
|
||||
|
||||
_flyingAllowedChanged = true;
|
||||
_ghostingAllowedChanged = true;
|
||||
}
|
||||
|
||||
// The minimum bounding box for the entity.
|
||||
|
@ -1880,6 +1900,13 @@ QList<QString> EntityItemProperties::listChangedProperties() {
|
|||
out += "queryAACube";
|
||||
}
|
||||
|
||||
if (flyingAllowedChanged()) {
|
||||
out += "flyingAllowed";
|
||||
}
|
||||
if (ghostingAllowedChanged()) {
|
||||
out += "ghostingAllowed";
|
||||
}
|
||||
|
||||
getAnimation().listChangedProperties(out);
|
||||
getKeyLight().listChangedProperties(out);
|
||||
getSkybox().listChangedProperties(out);
|
||||
|
|
|
@ -205,6 +205,9 @@ public:
|
|||
DEFINE_PROPERTY_REF(PROP_JOINT_TRANSLATIONS_SET, JointTranslationsSet, jointTranslationsSet, QVector<bool>, QVector<bool>());
|
||||
DEFINE_PROPERTY_REF(PROP_JOINT_TRANSLATIONS, JointTranslations, jointTranslations, QVector<glm::vec3>, QVector<glm::vec3>());
|
||||
|
||||
DEFINE_PROPERTY(PROP_FLYING_ALLOWED, FlyingAllowed, flyingAllowed, bool, ZoneEntityItem::DEFAULT_FLYING_ALLOWED);
|
||||
DEFINE_PROPERTY(PROP_GHOSTING_ALLOWED, GhostingAllowed, ghostingAllowed, bool, ZoneEntityItem::DEFAULT_GHOSTING_ALLOWED);
|
||||
|
||||
static QString getBackgroundModeString(BackgroundMode mode);
|
||||
|
||||
|
||||
|
@ -416,6 +419,9 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
|
|||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, JointTranslationsSet, jointTranslationsSet, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, JointTranslations, jointTranslations, "");
|
||||
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, FlyingAllowed, flyingAllowed, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, GhostingAllowed, ghostingAllowed, "");
|
||||
|
||||
properties.getAnimation().debugDump();
|
||||
properties.getSkybox().debugDump();
|
||||
properties.getStage().debugDump();
|
||||
|
|
|
@ -169,6 +169,9 @@ enum EntityPropertyList {
|
|||
|
||||
PROP_FALLOFF_RADIUS, // for Light entity
|
||||
|
||||
PROP_FLYING_ALLOWED, // can avatars in a zone fly?
|
||||
PROP_GHOSTING_ALLOWED, // can avatars in a zone turn off physics?
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ATTENTION: add new properties to end of list just ABOVE this line
|
||||
PROP_AFTER_LAST_ITEM,
|
||||
|
|
|
@ -23,8 +23,12 @@
|
|||
bool ZoneEntityItem::_zonesArePickable = false;
|
||||
bool ZoneEntityItem::_drawZoneBoundaries = false;
|
||||
|
||||
|
||||
const ShapeType ZoneEntityItem::DEFAULT_SHAPE_TYPE = SHAPE_TYPE_BOX;
|
||||
const QString ZoneEntityItem::DEFAULT_COMPOUND_SHAPE_URL = "";
|
||||
const bool ZoneEntityItem::DEFAULT_FLYING_ALLOWED = true;
|
||||
const bool ZoneEntityItem::DEFAULT_GHOSTING_ALLOWED = true;
|
||||
|
||||
|
||||
EntityItemPointer ZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new ZoneEntityItem(entityID) };
|
||||
|
@ -55,6 +59,9 @@ EntityItemProperties ZoneEntityItem::getProperties(EntityPropertyFlags desiredPr
|
|||
|
||||
_skyboxProperties.getProperties(properties);
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(flyingAllowed, getFlyingAllowed);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(ghostingAllowed, getGhostingAllowed);
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
@ -70,6 +77,9 @@ bool ZoneEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(backgroundMode, setBackgroundMode);
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(flyingAllowed, setFlyingAllowed);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(ghostingAllowed, setGhostingAllowed);
|
||||
|
||||
bool somethingChangedInSkybox = _skyboxProperties.setProperties(properties);
|
||||
|
||||
somethingChanged = somethingChanged || somethingChangedInKeyLight || somethingChangedInStage || somethingChangedInSkybox;
|
||||
|
@ -116,6 +126,9 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
bytesRead += bytesFromSkybox;
|
||||
dataAt += bytesFromSkybox;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_FLYING_ALLOWED, bool, setFlyingAllowed);
|
||||
READ_ENTITY_PROPERTY(PROP_GHOSTING_ALLOWED, bool, setGhostingAllowed);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
|
@ -125,13 +138,16 @@ EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& p
|
|||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||
|
||||
requestedProperties += _keyLightProperties.getEntityProperties(params);
|
||||
|
||||
|
||||
requestedProperties += PROP_SHAPE_TYPE;
|
||||
requestedProperties += PROP_COMPOUND_SHAPE_URL;
|
||||
requestedProperties += PROP_BACKGROUND_MODE;
|
||||
requestedProperties += _stageProperties.getEntityProperties(params);
|
||||
requestedProperties += _skyboxProperties.getEntityProperties(params);
|
||||
|
||||
|
||||
requestedProperties += PROP_FLYING_ALLOWED;
|
||||
requestedProperties += PROP_GHOSTING_ALLOWED;
|
||||
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
|
@ -155,10 +171,12 @@ void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
|
|||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, (uint32_t)getShapeType());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, getCompoundShapeURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_BACKGROUND_MODE, (uint32_t)getBackgroundMode()); // could this be a uint16??
|
||||
|
||||
|
||||
_skyboxProperties.appendSubclassData(packetData, params, modelTreeElementExtraEncodeData, requestedProperties,
|
||||
propertyFlags, propertiesDidntFit, propertyCount, appendState);
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_FLYING_ALLOWED, getFlyingAllowed());
|
||||
APPEND_ENTITY_PROPERTY(PROP_GHOSTING_ALLOWED, getGhostingAllowed());
|
||||
}
|
||||
|
||||
void ZoneEntityItem::debugDump() const {
|
||||
|
|
|
@ -70,6 +70,11 @@ public:
|
|||
const SkyboxPropertyGroup& getSkyboxProperties() const { return _skyboxProperties; }
|
||||
const StagePropertyGroup& getStageProperties() const { return _stageProperties; }
|
||||
|
||||
bool getFlyingAllowed() const { return _flyingAllowed; }
|
||||
void setFlyingAllowed(bool value) { _flyingAllowed = value; }
|
||||
bool getGhostingAllowed() const { return _ghostingAllowed; }
|
||||
void setGhostingAllowed(bool value) { _ghostingAllowed = value; }
|
||||
|
||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||
|
@ -80,18 +85,23 @@ public:
|
|||
|
||||
static const ShapeType DEFAULT_SHAPE_TYPE;
|
||||
static const QString DEFAULT_COMPOUND_SHAPE_URL;
|
||||
|
||||
static const bool DEFAULT_FLYING_ALLOWED;
|
||||
static const bool DEFAULT_GHOSTING_ALLOWED;
|
||||
|
||||
protected:
|
||||
KeyLightPropertyGroup _keyLightProperties;
|
||||
|
||||
|
||||
ShapeType _shapeType = DEFAULT_SHAPE_TYPE;
|
||||
QString _compoundShapeURL;
|
||||
|
||||
|
||||
BackgroundMode _backgroundMode = BACKGROUND_MODE_INHERIT;
|
||||
|
||||
StagePropertyGroup _stageProperties;
|
||||
SkyboxPropertyGroup _skyboxProperties;
|
||||
|
||||
bool _flyingAllowed { DEFAULT_FLYING_ALLOWED };
|
||||
bool _ghostingAllowed { DEFAULT_GHOSTING_ALLOWED };
|
||||
|
||||
static bool _drawZoneBoundaries;
|
||||
static bool _zonesArePickable;
|
||||
};
|
||||
|
|
|
@ -47,7 +47,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::EntityAdd:
|
||||
case PacketType::EntityEdit:
|
||||
case PacketType::EntityData:
|
||||
return VERSION_LIGHT_HAS_FALLOFF_RADIUS;
|
||||
return VERSION_ENTITIES_NO_FLY_ZONES;
|
||||
case PacketType::AvatarData:
|
||||
case PacketType::BulkAvatarData:
|
||||
return static_cast<PacketVersion>(AvatarMixerPacketVersion::SoftAttachmentSupport);
|
||||
|
|
|
@ -171,6 +171,7 @@ const PacketVersion VERSION_ENTITITES_HAVE_QUERY_BOX = 54;
|
|||
const PacketVersion VERSION_ENTITITES_HAVE_COLLISION_MASK = 55;
|
||||
const PacketVersion VERSION_ATMOSPHERE_REMOVED = 56;
|
||||
const PacketVersion VERSION_LIGHT_HAS_FALLOFF_RADIUS = 57;
|
||||
const PacketVersion VERSION_ENTITIES_NO_FLY_ZONES = 58;
|
||||
|
||||
enum class AvatarMixerPacketVersion : PacketVersion {
|
||||
TranslationSupport = 17,
|
||||
|
|
|
@ -264,6 +264,10 @@ void CharacterController::setState(State desiredState, const char* reason) {
|
|||
#else
|
||||
void CharacterController::setState(State desiredState) {
|
||||
#endif
|
||||
if (!_flyingAllowed && desiredState == State::Hover) {
|
||||
desiredState = State::InAir;
|
||||
}
|
||||
|
||||
if (desiredState != _state) {
|
||||
#ifdef DEBUG_STATE_CHANGE
|
||||
qCDebug(physics) << "CharacterController::setState" << stateToStr(desiredState) << "from" << stateToStr(_state) << "," << reason;
|
||||
|
@ -644,3 +648,13 @@ bool CharacterController::getRigidBodyLocation(glm::vec3& avatarRigidBodyPositio
|
|||
avatarRigidBodyRotation = bulletToGLM(worldTrans.getRotation());
|
||||
return true;
|
||||
}
|
||||
|
||||
void CharacterController::setFlyingAllowed(bool value) {
|
||||
if (_flyingAllowed != value) {
|
||||
_flyingAllowed = value;
|
||||
|
||||
if (!_flyingAllowed && _state == State::Hover) {
|
||||
SET_STATE(State::InAir, "flying not allowed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,6 +110,9 @@ public:
|
|||
|
||||
bool getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation);
|
||||
|
||||
void setFlyingAllowed(bool value);
|
||||
|
||||
|
||||
protected:
|
||||
#ifdef DEBUG_STATE_CHANGE
|
||||
void setState(State state, const char* reason);
|
||||
|
@ -172,6 +175,8 @@ protected:
|
|||
btRigidBody* _rigidBody { nullptr };
|
||||
uint32_t _pendingFlags { 0 };
|
||||
uint32_t _previousFlags { 0 };
|
||||
|
||||
bool _flyingAllowed { true };
|
||||
};
|
||||
|
||||
#endif // hifi_CharacterControllerInterface_h
|
||||
|
|
|
@ -484,6 +484,9 @@
|
|||
var elZoneSkyboxColorGreen = document.getElementById("property-zone-skybox-color-green");
|
||||
var elZoneSkyboxColorBlue = document.getElementById("property-zone-skybox-color-blue");
|
||||
var elZoneSkyboxURL = document.getElementById("property-zone-skybox-url");
|
||||
|
||||
var elZoneFlyingAllowed = document.getElementById("property-zone-flying-allowed");
|
||||
var elZoneGhostingAllowed = document.getElementById("property-zone-ghosting-allowed");
|
||||
|
||||
var elPolyVoxSections = document.querySelectorAll(".poly-vox-section");
|
||||
allSections.push(elPolyVoxSections);
|
||||
|
@ -771,6 +774,9 @@
|
|||
elZoneSkyboxColorGreen.value = properties.skybox.color.green;
|
||||
elZoneSkyboxColorBlue.value = properties.skybox.color.blue;
|
||||
elZoneSkyboxURL.value = properties.skybox.url;
|
||||
|
||||
elZoneFlyingAllowed.checked = properties.flyingAllowed;
|
||||
elZoneGhostingAllowed.checked = properties.ghostingAllowed;
|
||||
|
||||
showElements(document.getElementsByClassName('skybox-section'), elZoneBackgroundMode.value == 'skybox');
|
||||
} else if (properties.type == "PolyVox") {
|
||||
|
@ -1077,7 +1083,10 @@
|
|||
}));
|
||||
|
||||
elZoneSkyboxURL.addEventListener('change', createEmitGroupTextPropertyUpdateFunction('skybox','url'));
|
||||
|
||||
|
||||
elZoneFlyingAllowed.addEventListener('change', createEmitCheckedPropertyUpdateFunction('flyingAllowed'));
|
||||
elZoneGhostingAllowed.addEventListener('change', createEmitCheckedPropertyUpdateFunction('ghostingAllowed'));
|
||||
|
||||
var voxelVolumeSizeChangeFunction = createEmitVec3PropertyUpdateFunction(
|
||||
'voxelVolumeSize', elVoxelVolumeSizeX, elVoxelVolumeSizeY, elVoxelVolumeSizeZ);
|
||||
elVoxelVolumeSizeX.addEventListener('change', voxelVolumeSizeChangeFunction);
|
||||
|
@ -1792,6 +1801,15 @@
|
|||
<input type="text" id="property-zone-skybox-url">
|
||||
</div>
|
||||
|
||||
<div class="zone-group zone-section property checkbox">
|
||||
<input type="checkbox" id="property-zone-flying-allowed">
|
||||
<label for="property-zone-flying-allowed"> Flying Allowed</label>
|
||||
</div>
|
||||
<div class="zone-group zone-section property checkbox">
|
||||
<input type="checkbox" id="property-zone-ghosting-allowed">
|
||||
<label for="property-zone-ghosting-allowed"> Ghosting Allowed</label>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="section-header web-group web-section">
|
||||
<label>Web</label><span>M</span>
|
||||
|
|
Loading…
Reference in a new issue