Пример #1
0
void TypeConstraint::verifyFail(const Func* func, int paramNum,
                                TypedValue* tv) const {
  JIT::VMRegAnchor _;

  const StringData* tn = typeName();
  if (isSelf()) {
    selfToTypeName(func, &tn);
  } else if (isParent()) {
    parentToTypeName(func, &tn);
  }

  auto const givenType = describe_actual_type(tv);

  auto c = tvToCell(tv);
  if (isArray() && !isSoft() && !func->mustBeRef(paramNum) &&
      c->m_type == KindOfObject && c->m_data.pobj->isCollection()) {
    // To ease migration, the 'array' type constraint will implicitly cast
    // collections to arrays, provided the type constraint is not soft and
    // the parameter is not by reference. We raise a notice to let the user
    // know that there was a type mismatch and that an implicit conversion
    // was performed.
    raise_notice(
      folly::format(
        "Argument {} to {}() must be of type {}, {} given; argument {} was "
        "implicitly cast to array",
        paramNum + 1, func->fullName()->data(), fullName(), givenType,
        paramNum + 1
      ).str()
    );
    tvCastToArrayInPlace(tv);
    return;
  }

  if (isExtended() && isSoft()) {
    // Soft extended type hints raise warnings instead of recoverable
    // errors, to ease migration.
    raise_debugging(
      "Argument %d to %s() must be of type %s, %s given",
      paramNum + 1, func->fullName()->data(), fullName().c_str(), givenType);
  } else if (isExtended() && isNullable()) {
    raise_typehint_error(
      folly::format(
        "Argument {} to {}() must be of type {}, {} given",
        paramNum + 1, func->fullName()->data(), fullName(), givenType
      ).str()
    );
  } else {
    raise_typehint_error(
      folly::format(
        "Argument {} passed to {}() must be an instance of {}, {} given",
        paramNum + 1, func->fullName()->data(), tn->data(), givenType
      ).str()
    );
  }
}
Пример #2
0
void TypeConstraint::verifyFail(const Func* func, int paramNum,
                                const TypedValue* tv) const {
  Transl::VMRegAnchor _;
  std::ostringstream fname;
  fname << func->fullName()->data() << "()";
  const StringData* tn = typeName();
  if (isSelf()) {
    selfToTypeName(func, &tn);
  } else if (isParent()) {
    parentToTypeName(func, &tn);
  }

  auto const givenType = describe_actual_type(tv);

  if (isExtended()) {
    // Extended type hints raise warnings instead of recoverable
    // errors for now, to ease migration (we used to not check these
    // at all at runtime).
    assert(nullable() &&
           "only nullable extended type hints are currently supported");
    raise_warning(
      "Argument %d to %s must be of type ?%s, %s given",
      paramNum + 1, fname.str().c_str(), tn->data(), givenType);
  } else {
    raise_recoverable_error(
      "Argument %d passed to %s must be an instance of %s, %s given",
      paramNum + 1, fname.str().c_str(), tn->data(), givenType);
  }
}
Пример #3
0
bool TypeConstraint::compat(const TypeConstraint& other) const {
  if (other.isExtended() || isExtended()) {
    /*
     * Rely on the ahead of time typechecker---checking here can
     * make it harder to convert a base class or interface to <?hh,
     * because derived classes that are still <?php would all need
     * to be modified.
     */
    return true;
  }

  if (m_typeName == other.m_typeName) {
    return true;
  }

  if (m_typeName && other.m_typeName) {
    if (m_typeName->isame(other.m_typeName)) {
      return true;
    }

    const Class* cls = Unit::lookupClass(m_typeName);
    const Class* otherCls = Unit::lookupClass(other.m_typeName);

    return cls && otherCls && cls == otherCls;
  }

  return false;
}
Пример #4
0
uint32_t CanMessage::getId() const {
	if (isExtended()) {
		return _raw_id & id_mask_extended;
	} else {
		return _raw_id & id_mask_standard;
	}
}
Пример #5
0
QString CanMessage::getIdString() const
{
    if (isExtended()) {
        return QString().sprintf("0x%08X", getId());
    } else {
        return QString().sprintf("0x%03X", getId());
    }
}
Пример #6
0
/*!
    \fn void QPaintEngine::syncState()

    \internal

    Updates all dirty states in this engine. This function should ONLY
    be used when drawing with native handles directly and immediate sync
    from QPainters state to the native state is required.
*/
void QPaintEngine::syncState()
{
    Q_ASSERT(state);
    updateState(*state);

    if (isExtended())
        static_cast<QPaintEngineEx *>(this)->sync();
}
Пример #7
0
std::string TypeConstraint::displayName(const Func* func /*= nullptr*/) const {
  const StringData* tn = typeName();
  std::string name;
  if (isSoft()) {
    name += '@';
  }
  if (isNullable() && isExtended()) {
    name += '?';
  }
  if (func && isSelf()) {
    selfToTypeName(func, &tn);
    name += tn->data();
  } else if (func && isParent()) {
    parentToTypeName(func, &tn);
    name += tn->data();
  } else {
    const char* str = tn->data();
    auto len = tn->size();
    if (len > 3 && tolower(str[0]) == 'h' && tolower(str[1]) == 'h' &&
        str[2] == '\\') {
      bool strip = false;
      const char* stripped = str + 3;
      switch (len - 3) {
        case 3:
          strip = (!strcasecmp(stripped, "int") ||
                   !strcasecmp(stripped, "num"));
          break;
        case 4: strip = !strcasecmp(stripped, "bool"); break;
        case 5: strip = !strcasecmp(stripped, "float"); break;
        case 6: strip = !strcasecmp(stripped, "string"); break;
        case 8:
          strip = (!strcasecmp(stripped, "resource") ||
                   !strcasecmp(stripped, "noreturn") ||
                   !strcasecmp(stripped, "arraykey"));
          break;
        default:
          break;
      }
      if (strip) {
        str = stripped;
      }
    }
    name += str;
  }
  return name;
}
Пример #8
0
void TypeConstraint::verifyFail(const Func* func, int paramNum,
                                const TypedValue* tv) const {
  Transl::VMRegAnchor _;
  std::ostringstream fname;
  fname << func->fullName()->data() << "()";
  const StringData* tn = typeName();
  if (isSelf()) {
    selfToTypeName(func, &tn);
  } else if (isParent()) {
    parentToTypeName(func, &tn);
  }

  auto const givenType = describe_actual_type(tv);

  if (isExtended()) {
    if (isSoft()) {
      // Soft type hints raise warnings instead of recoverable
      // errors by design, to ease migration.
      raise_warning(
        "Argument %d passed to %s must be of type %s, %s given",
        paramNum + 1, fname.str().c_str(), fullName().c_str(), givenType);
    } else if (isNullable()) {
      // This error message is slightly different from the normal case
      // (fullName() vs tn)
      raise_recoverable_error(
        "Argument %d passed to %s must be of type %s, %s given",
        paramNum + 1, fname.str().c_str(), fullName().c_str(), givenType);
    } else {
      assert(false &&
        "Only nullable and soft extended type hints are currently implemented");
    }
  } else {
    raise_recoverable_error(
      "Argument %d passed to %s must be an instance of %s, %s given",
      paramNum + 1, fname.str().c_str(), tn->data(), givenType);
  }
}
//slot
void KShortcutsEditorDelegate::itemActivated(QModelIndex index)
{
    //As per our constructor our parent *is* a QTreeWidget
    QTreeWidget *view = static_cast<QTreeWidget *>(parent());

    KShortcutsEditorItem *item = KShortcutsEditorPrivate::itemFromIndex(view, index);
    if (!item) {
        //that probably was a non-leaf (type() !=ActionItem) item
        return;
    }

    int column = index.column();
    if (column == Name) {
        // If user click in the name column activate the (Global|Local)Primary
        // column if possible.
        if (!view->header()->isSectionHidden(LocalPrimary)) {
            column = LocalPrimary;
        } else if (!view->header()->isSectionHidden(GlobalPrimary)) {
            column = GlobalPrimary;
        } else {
            // do nothing.
        }
        index = index.sibling(index.row(), column);
        view->selectionModel()->select(index, QItemSelectionModel::SelectCurrent);
    }

    // Check if the models wants us to edit the item at index
    if (!index.data(ShowExtensionIndicatorRole).value<bool>()) {
        return;
    }

    if (!isExtended(index)) {
        //we only want maximum ONE extender open at any time.
        if (m_editingIndex.isValid()) {
            KShortcutsEditorItem *oldItem = KShortcutsEditorPrivate::itemFromIndex(view,
                                            m_editingIndex);
            Q_ASSERT(oldItem); //here we really expect nothing but a real KShortcutsEditorItem

            oldItem->setNameBold(false);
            contractItem(m_editingIndex);
        }

        m_editingIndex = index;
        QWidget *viewport = static_cast<QAbstractItemView *>(parent())->viewport();

        if (column >= LocalPrimary && column <= GlobalAlternate) {
            ShortcutEditWidget *editor = new ShortcutEditWidget(viewport,
                    index.data(DefaultShortcutRole).value<QKeySequence>(),
                    index.data(ShortcutRole).value<QKeySequence>(),
                    m_allowLetterShortcuts);
            if (column == GlobalPrimary) {
                QObject *action = index.data(ObjectRole).value<QObject *>();
                editor->setAction(action);
                editor->setMultiKeyShortcutsAllowed(false);
                QString componentName = action->property("componentName").toString();
                if (componentName.isEmpty()) {
                    componentName = QCoreApplication::applicationName();
                }
                editor->setComponentName(componentName);
            }

            m_editor = editor;
            // For global shortcuts check against the kde standard shortcuts
            if (column == GlobalPrimary || column == GlobalAlternate) {
                editor->setCheckForConflictsAgainst(
                    KKeySequenceWidget::LocalShortcuts
                    | KKeySequenceWidget::GlobalShortcuts
                    | KKeySequenceWidget::StandardShortcuts);
            }

            editor->setCheckActionCollections(m_checkActionCollections);

            connect(m_editor, SIGNAL(keySequenceChanged(QKeySequence)),
                    this, SLOT(keySequenceChanged(QKeySequence)));
            connect(m_editor, SIGNAL(stealShortcut(QKeySequence,QAction*)),
                    this, SLOT(stealShortcut(QKeySequence,QAction*)));

        } else if (column == RockerGesture) {
Пример #10
0
void TypeConstraint::init() {
  if (UNLIKELY(s_typeNamesToTypes.empty())) {
    const struct Pair {
      const StringData* name;
      Type type;
    } pairs[] = {
      { StringData::GetStaticString("bool"),     { KindOfBoolean,
                                                   MetaType::Precise }},
      { StringData::GetStaticString("boolean"),  { KindOfBoolean,
                                                   MetaType::Precise }},

      { StringData::GetStaticString("int"),      { KindOfInt64,
                                                   MetaType::Precise }},
      { StringData::GetStaticString("integer"),  { KindOfInt64,
                                                   MetaType::Precise }},

      { StringData::GetStaticString("real"),     { KindOfDouble,
                                                   MetaType::Precise }},
      { StringData::GetStaticString("double"),   { KindOfDouble,
                                                   MetaType::Precise }},
      { StringData::GetStaticString("float"),    { KindOfDouble,
                                                   MetaType::Precise }},

      { StringData::GetStaticString("string"),   { KindOfString,
                                                   MetaType::Precise }},

      { StringData::GetStaticString("array"),    { KindOfArray,
                                                   MetaType::Precise }},

      { StringData::GetStaticString("resource"), { KindOfResource,
                                                   MetaType::Precise }},

      { StringData::GetStaticString("self"),     { KindOfObject,
                                                   MetaType::Self }},
      { StringData::GetStaticString("parent"),   { KindOfObject,
                                                   MetaType::Parent }},
      { StringData::GetStaticString("callable"), { KindOfObject,
                                                   MetaType::Callable }},
    };
    for (unsigned i = 0; i < sizeof(pairs) / sizeof(Pair); ++i) {
      s_typeNamesToTypes[pairs[i].name] = pairs[i].type;
    }
  }

  if (m_typeName && isExtended()) {
    assert(nullable() &&
           "Only nullable extended type hints are implemented");
  }

  if (blacklistedName(m_typeName)) {
    m_typeName = nullptr;
  }
  if (m_typeName == nullptr) {
    m_type.m_dt = KindOfInvalid;
    m_type.m_metatype = MetaType::Precise;
    return;
  }

  Type dtype;
  TRACE(5, "TypeConstraint: this %p type %s, nullable %d\n",
        this, m_typeName->data(), nullable());
  if (!mapGet(s_typeNamesToTypes, m_typeName, &dtype) ||
      !(hhType() || dtype.m_dt == KindOfArray || dtype.isParent() ||
        dtype.isSelf())) {
    TRACE(5, "TypeConstraint: this %p no such type %s, treating as object\n",
          this, m_typeName->data());
    m_type = { KindOfObject, MetaType::Precise };
    m_namedEntity = Unit::GetNamedEntity(m_typeName);
    TRACE(5, "TypeConstraint: NamedEntity: %p\n", m_namedEntity);
    return;
  }
  m_type = dtype;
  assert(m_type.m_dt != KindOfStaticString);
  assert(IMPLIES(isParent(), m_type.m_dt == KindOfObject));
  assert(IMPLIES(isSelf(), m_type.m_dt == KindOfObject));
  assert(IMPLIES(isCallable(), m_type.m_dt == KindOfObject));
}
Пример #11
0
void TypeConstraint::verifyFail(const Func* func, TypedValue* tv,
                                int id, bool useStrictTypes) const {
  VMRegAnchor _;
  std::string name = displayName(func);
  auto const givenType = describe_actual_type(tv, isHHType());

  if (UNLIKELY(!useStrictTypes)) {
    if (auto dt = underlyingDataType()) {
      // In non-strict mode we may be able to coerce a type failure. For object
      // typehints there is no possible coercion in the failure case, but HNI
      // builtins currently only guard on kind not class so the following wil
      // generate false positives for objects.
      if (*dt != KindOfObject) {
        // HNI conversions implicitly unbox references, this behavior is wrong,
        // in particular it breaks the way type conversion works for PHP 7
        // scalar type hints
        if (tv->m_type == KindOfRef) {
          auto inner = tv->m_data.pref->var()->asTypedValue();
          if (tvCoerceParamInPlace(inner, *dt)) {
            tvAsVariant(tv) = tvAsVariant(inner);
            return;
          }
        } else {
          if (tvCoerceParamInPlace(tv, *dt)) return;
        }
      }
    }
  } else if (UNLIKELY(!func->unit()->isHHFile() &&
                      !RuntimeOption::EnableHipHopSyntax)) {
    // PHP 7 allows for a widening conversion from Int to Float. We still ban
    // this in HH files.
    if (auto dt = underlyingDataType()) {
      if (*dt == KindOfDouble && tv->m_type == KindOfInt64 &&
          tvCoerceParamToDoubleInPlace(tv)) {
        return;
      }
    }
  }

  // Handle return type constraint failures
  if (id == ReturnId) {
    std::string msg;
    if (func->isClosureBody()) {
      msg =
        folly::format(
          "Value returned from {}closure must be of type {}, {} given",
          func->isAsync() ? "async " : "",
          name,
          givenType
        ).str();
    } else {
      msg =
        folly::format(
          "Value returned from {}{} {}() must be of type {}, {} given",
          func->isAsync() ? "async " : "",
          func->preClass() ? "method" : "function",
          func->fullName(),
          name,
          givenType
        ).str();
    }
    if (RuntimeOption::EvalCheckReturnTypeHints >= 2 && !isSoft()) {
      raise_return_typehint_error(msg);
    } else {
      raise_warning_unsampled(msg);
    }
    return;
  }

  // Handle implicit collection->array conversion for array parameter type
  // constraints
  auto c = tvToCell(tv);
  if (isArray() && !isSoft() && !func->mustBeRef(id) &&
      c->m_type == KindOfObject && c->m_data.pobj->isCollection()) {
    // To ease migration, the 'array' type constraint will implicitly cast
    // collections to arrays, provided the type constraint is not soft and
    // the parameter is not by reference. We raise a notice to let the user
    // know that there was a type mismatch and that an implicit conversion
    // was performed.
    raise_notice(
      folly::format(
        "Argument {} to {}() must be of type {}, {} given; argument {} was "
        "implicitly cast to array",
        id + 1, func->fullName(), name, givenType, id + 1
      ).str()
    );
    tvCastToArrayInPlace(tv);
    return;
  }

  // Handle parameter type constraint failures
  if (isExtended() && isSoft()) {
    // Soft extended type hints raise warnings instead of recoverable
    // errors, to ease migration.
    raise_warning_unsampled(
      folly::format(
        "Argument {} to {}() must be of type {}, {} given",
        id + 1, func->fullName(), name, givenType
      ).str()
    );
  } else if (isExtended() && isNullable()) {
    raise_typehint_error(
      folly::format(
        "Argument {} to {}() must be of type {}, {} given",
        id + 1, func->fullName(), name, givenType
      ).str()
    );
  } else {
    auto cls = Unit::lookupClass(m_typeName);
    if (cls && isInterface(cls)) {
      raise_typehint_error(
        folly::format(
          "Argument {} passed to {}() must implement interface {}, {} given",
          id + 1, func->fullName(), name, givenType
        ).str()
      );
    } else {
      raise_typehint_error(
        folly::format(
          "Argument {} passed to {}() must be an instance of {}, {} given",
          id + 1, func->fullName(), name, givenType
        ).str()
      );
    }
  }
}
Пример #12
0
void TypeConstraint::init() {
  if (UNLIKELY(s_typeNamesToTypes.empty())) {
    const struct Pair {
      const StringData* name;
      Type type;
    } pairs[] = {
      { makeStaticString("bool"),     { KindOfBoolean,
                                                   MetaType::Precise }},
      { makeStaticString("boolean"),  { KindOfBoolean,
                                                   MetaType::Precise }},

      { makeStaticString("int"),      { KindOfInt64,
                                                   MetaType::Precise }},
      { makeStaticString("integer"),  { KindOfInt64,
                                                   MetaType::Precise }},

      { makeStaticString("real"),     { KindOfDouble,
                                                   MetaType::Precise }},
      { makeStaticString("double"),   { KindOfDouble,
                                                   MetaType::Precise }},
      { makeStaticString("float"),    { KindOfDouble,
                                                   MetaType::Precise }},

      { makeStaticString("string"),   { KindOfString,
                                                   MetaType::Precise }},

      { makeStaticString("array"),    { KindOfArray,
                                                   MetaType::Precise }},

      { makeStaticString("resource"), { KindOfResource,
                                                   MetaType::Precise }},

      { makeStaticString("self"),     { KindOfObject,
                                                   MetaType::Self }},
      { makeStaticString("parent"),   { KindOfObject,
                                                   MetaType::Parent }},
      { makeStaticString("callable"), { KindOfObject,
                                                   MetaType::Callable }},
      { makeStaticString("num"),      { KindOfDouble,
                                                   MetaType::Number }},

    };
    for (unsigned i = 0; i < sizeof(pairs) / sizeof(Pair); ++i) {
      s_typeNamesToTypes[pairs[i].name] = pairs[i].type;
    }
  }

  if (isTypeVar()) {
    // We kept the type variable type constraint to correctly check child
    // classes implementing abstract methods or interfaces.
    m_type.dt = KindOfInvalid;
    m_type.metatype = MetaType::Precise;
    return;
  }
  if (m_typeName && isExtended()) {
    assert((isNullable() || isSoft()) &&
           "Only nullable and soft extended type hints are implemented");
  }

  if (m_typeName == nullptr) {
    m_type.dt = KindOfInvalid;
    m_type.metatype = MetaType::Precise;
    return;
  }

  Type dtype;
  TRACE(5, "TypeConstraint: this %p type %s, nullable %d\n",
        this, m_typeName->data(), isNullable());
  auto const mptr = folly::get_ptr(s_typeNamesToTypes, m_typeName);
  if (mptr) dtype = *mptr;
  if (!mptr ||
      !(isHHType() || dtype.dt == KindOfArray ||
        dtype.metatype == MetaType::Parent ||
        dtype.metatype == MetaType::Self ||
        dtype.metatype == MetaType::Callable)) {
    TRACE(5, "TypeConstraint: this %p no such type %s, treating as object\n",
          this, m_typeName->data());
    m_type = { KindOfObject, MetaType::Precise };
    m_namedEntity = Unit::GetNamedEntity(m_typeName);
    TRACE(5, "TypeConstraint: NamedEntity: %p\n", m_namedEntity);
    return;
  }
  m_type = dtype;
  assert(m_type.dt != KindOfStaticString);
  assert(IMPLIES(isParent(), m_type.dt == KindOfObject));
  assert(IMPLIES(isSelf(), m_type.dt == KindOfObject));
  assert(IMPLIES(isCallable(), m_type.dt == KindOfObject));
}
Пример #13
0
void TypeConstraint::verifyFail(const Func* func, TypedValue* tv,
                                int id) const {
  VMRegAnchor _;
  std::string name = displayName(func);
  auto const givenType = describe_actual_type(tv, isHHType());
  // Handle return type constraint failures
  if (id == ReturnId) {
    std::string msg;
    if (func->isClosureBody()) {
      msg =
        folly::format(
          "Value returned from {}closure must be of type {}, {} given",
          func->isAsync() ? "async " : "",
          name,
          givenType
        ).str();
    } else {
      msg =
        folly::format(
          "Value returned from {}{} {}() must be of type {}, {} given",
          func->isAsync() ? "async " : "",
          func->preClass() ? "method" : "function",
          func->fullName()->data(),
          name,
          givenType
        ).str();
    }
    if (RuntimeOption::EvalCheckReturnTypeHints >= 2 && !isSoft() &&
        (!func->isClosureBody() ||
         !RuntimeOption::EvalSoftClosureReturnTypeHints)) {
      raise_return_typehint_error(msg);
    } else {
      raise_debugging(msg);
    }
    return;
  }
  // Handle implicit collection->array conversion for array parameter type
  // constraints
  auto c = tvToCell(tv);
  if (isArray() && !isSoft() && !func->mustBeRef(id) &&
      c->m_type == KindOfObject && c->m_data.pobj->isCollection()) {
    // To ease migration, the 'array' type constraint will implicitly cast
    // collections to arrays, provided the type constraint is not soft and
    // the parameter is not by reference. We raise a notice to let the user
    // know that there was a type mismatch and that an implicit conversion
    // was performed.
    raise_notice(
      folly::format(
        "Argument {} to {}() must be of type {}, {} given; argument {} was "
        "implicitly cast to array",
        id + 1, func->fullName()->data(), name, givenType, id + 1
      ).str()
    );
    tvCastToArrayInPlace(tv);
    return;
  }
  // Handle parameter type constraint failures
  if (isExtended() && isSoft()) {
    // Soft extended type hints raise warnings instead of recoverable
    // errors, to ease migration.
    raise_debugging(
      folly::format(
        "Argument {} to {}() must be of type {}, {} given",
        id + 1, func->fullName()->data(), name, givenType
      ).str()
    );
  } else if (isExtended() && isNullable()) {
    raise_typehint_error(
      folly::format(
        "Argument {} to {}() must be of type {}, {} given",
        id + 1, func->fullName()->data(), name, givenType
      ).str()
    );
  } else {
    auto cls = Unit::lookupClass(m_typeName);
    if (cls && isInterface(cls)) {
      raise_typehint_error(
        folly::format(
          "Argument {} passed to {}() must implement interface {}, {} given",
          id + 1, func->fullName()->data(), name, givenType
        ).str()
      );
    } else {
      raise_typehint_error(
        folly::format(
          "Argument {} passed to {}() must be an instance of {}, {} given",
          id + 1, func->fullName()->data(), name, givenType
        ).str()
      );
    }
  }
}
Пример #14
0
// -----------------------------------------------------------------------------
// (Re)builds lists with information about all currently available resource
// textures and flats
// -----------------------------------------------------------------------------
void MapTextureManager::buildTexInfoList()
{
	// Clear
	tex_info_.clear();
	flat_info_.clear();

	// --- Textures ---

	// Composite textures
	vector<TextureResource::Texture*> textures;
	App::resources().putAllTextures(textures, App::archiveManager().baseResourceArchive());
	for (auto& texture : textures)
	{
		auto tex    = &texture->tex;
		auto parent = texture->parent;

		auto long_name = tex->name();
		auto path      = StrUtil::beforeLast(long_name, '/');

		if (tex->isExtended())
		{
			if (StrUtil::equalCI(tex->type(), "texture") || StrUtil::equalCI(tex->type(), "walltexture"))
				tex_info_.emplace_back(long_name, Category::ZDTextures, parent, path, tex->index(), long_name);
			else if (StrUtil::equalCI(tex->type(), "define"))
				tex_info_.emplace_back(long_name, Category::HiRes, parent, path, tex->index(), long_name);
			else if (StrUtil::equalCI(tex->type(), "flat"))
				flat_info_.emplace_back(long_name, Category::ZDTextures, parent, path, tex->index(), long_name);
			// Ignore graphics, patches and sprites
		}
		else
			tex_info_.emplace_back(long_name, Category::TextureX, parent, path, tex->index() + 1, long_name);
	}

	// Texture namespace patches (TX_)
	if (Game::configuration().featureSupported(Game::Feature::TxTextures))
	{
		vector<ArchiveEntry*> patches;
		App::resources().putAllPatchEntries(
			patches, nullptr, Game::configuration().featureSupported(Game::Feature::LongNames));
		for (auto& patch : patches)
		{
			if (patch->isInNamespace("textures") || patch->isInNamespace("hires"))
			{
				// Determine texture path if it's in a pk3
				auto long_name  = patch->path(true).erase(0, 1);
				auto short_name = StrUtil::truncate(patch->upperNameNoExt(), 8);
				auto path      = patch->path(false);

				tex_info_.emplace_back(short_name, Category::Tx, patch->parent(), path, 0, long_name);
			}
		}
	}

	// Flats
	vector<ArchiveEntry*> flats;
	App::resources().putAllFlatEntries(
		flats, nullptr, Game::configuration().featureSupported(Game::Feature::LongNames));
	for (auto& flat : flats)
	{
		// Determine flat path if it's in a pk3
		auto long_name  = flat->path(true).erase(0, 1);
		auto short_name = StrUtil::truncate(flat->upperNameNoExt(), 8);
		auto path      = flat->path(false);

		flat_info_.emplace_back(short_name, Category::None, flat->parent(), path, 0, long_name);
	}
}
Пример #15
0
// -----------------------------------------------------------------------------
// Returns the flat matching [name], loading it from resources if necessary.
// If [mixed] is true, textures are also searched if no matching flat is found
// -----------------------------------------------------------------------------
const MapTextureManager::Texture& MapTextureManager::flat(std::string_view name, bool mixed)
{
	// Get flat matching name
	auto& mtex = flats_[StrUtil::upper(name)];

	// Get desired filter type
	auto filter = OpenGL::TexFilter::Linear;
	if (map_tex_filter == 0)
		filter = OpenGL::TexFilter::NearestLinearMin;
	else if (map_tex_filter == 1)
		filter = OpenGL::TexFilter::Linear;
	else if (map_tex_filter == 2)
		filter = OpenGL::TexFilter::LinearMipmap;
	else if (map_tex_filter == 3)
		filter = OpenGL::TexFilter::NearestMipmap;

	// If the texture is loaded
	if (mtex.gl_id)
	{
		// If the texture filter matches the desired one, return it
		auto& tex_info = OpenGL::Texture::info(mtex.gl_id);
		if (tex_info.filter == filter)
			return mtex;
		else
		{
			// Otherwise, reload the texture
			OpenGL::Texture::clear(mtex.gl_id);
			mtex.gl_id = 0;
		}
	}

	if (mixed)
	{
		auto ctex = App::resources().getTexture(name, archive_);
		if (ctex && ctex->isExtended() && ctex->type() != "WallTexture")
		{
			SImage image;
			if (ctex->toImage(image, archive_, palette_.get(), true))
			{
				mtex.gl_id = OpenGL::Texture::createFromImage(image, palette_.get(), filter);

				double sx = ctex->scaleX();
				if (sx == 0)
					sx = 1.0;
				double sy = ctex->scaleY();
				if (sy == 0)
					sy = 1.0;

				mtex.scale         = { 1.0 / sx, 1.0 / sy };
				mtex.world_panning = ctex->worldPanning();

				return mtex;
			}
		}
	}

	// Flat not found, look for it
	// Palette8bit* pal = getResourcePalette();
	if (!mtex.gl_id)
	{
		auto entry = App::resources().getTextureEntry(name, "hires", archive_);
		if (entry == nullptr)
			entry = App::resources().getTextureEntry(name, "flats", archive_);
		if (entry == nullptr)
			entry = App::resources().getFlatEntry(name, archive_);
		if (entry)
		{
			SImage image;
			if (Misc::loadImageFromEntry(&image, entry))
				mtex.gl_id = OpenGL::Texture::createFromImage(image, palette_.get(), filter);
		}
	}

	// Not found
	if (!mtex.gl_id)
	{
		// Try textures if mixed
		if (mixed)
			return texture(name, false);

		// Otherwise use missing texture
		else
			mtex.gl_id = OpenGL::Texture::missingTexture();
	}

	return mtex;
}
Пример #16
0
// -----------------------------------------------------------------------------
// Checks all texture definitions for problems and alerts the user if any are
// found. Returns true if any problems were found, false otherwise
// -----------------------------------------------------------------------------
bool TextureXEditor::checkTextures()
{
	wxString problems = wxEmptyString;

	// Go through all texturex lists
	for (auto& texture_editor : texture_editors_)
	{
		// Go through all textures
		for (unsigned t = 0; t < texture_editor->txList().size(); t++)
		{
			// Get texture
			auto tex = texture_editor->txList().texture(t);

			// Check its patches are all valid
			if (tex->isExtended())
			{
				// Extended texture, check if each patch exists in any open archive (or as a composite texture)
				for (unsigned p = 0; p < tex->nPatches(); p++)
				{
					auto pentry = App::resources().getPatchEntry(tex->patch(p)->name());
					auto fentry = App::resources().getFlatEntry(tex->patch(p)->name());
					auto ptex   = App::resources().getTexture(tex->patch(p)->name());
					if (!pentry && !fentry && !ptex)
						problems += wxString::Format(
							"Texture %s contains invalid/unknown patch %s\n", tex->name(), tex->patch(p)->name());
				}
			}
			else
			{
				// Regular texture, check the patch table
				for (unsigned p = 0; p < tex->nPatches(); p++)
				{
					if (patch_table_.patchIndex(tex->patch(p)->name()) == -1)
						problems += wxString::Format(
							"Texture %s contains invalid/unknown patch %s\n", tex->name(), tex->patch(p)->name());
				}
			}
		}
	}

	// Go through patch table
	for (unsigned a = 0; a < patch_table_.nPatches(); a++)
	{
		// Check patch entry is valid
		auto& patch = patch_table_.patch(a);
		auto  entry = App::resources().getPatchEntry(patch.name, "patches", archive_);

		if (!entry)
		{
			problems += wxString::Format("Patch %s cannot be found in any open archive\n", patch.name);
		}
		else
		{
			// Check patch entry type
			if (entry->type() == EntryType::unknownType())
				EntryType::detectEntryType(entry);
			auto type = entry->type();

			if (!type->extraProps().propertyExists("patch"))
				problems += wxString::Format(
					"Patch %s is of type \"%s\", which is not a valid gfx format for patches. "
					"Convert it to either Doom Gfx or PNG\n",
					patch.name,
					type->name());
		}
	}

	// Display a message box with any problems found
	if (!problems.IsEmpty())
	{
		ExtMessageDialog dlg(this, "Problems Found");
		dlg.setMessage("The following problems were found:");
		dlg.setExt(problems);
		dlg.ShowModal();

		return true;
	}
	else
		return false;
}