bool OptimizedTextureInfo::PlaceRect(ff::RectInt rect) { ff::RectInt rectCells( rect.left / s_gridSize, rect.top / s_gridSize, (rect.right + s_gridSize - 1) / s_gridSize, (rect.bottom + s_gridSize - 1) / s_gridSize); assertRetVal( rect.left >= 0 && rect.right <= _size.x && rect.top >= 0 && rect.bottom <= _size.y && rect.Width() > 0 && rect.Height() > 0, false); // Validate that the sprite doesn't overlap anything for (int y = rectCells.top - 1; y <= rectCells.bottom; y++) { if (y >= 0 && y < _size.y / s_gridSize && y < _countof(_rowRight)) { // Must be a one cell gap between sprites assertRetVal(!_rowRight[y] || _rowRight[y] + 1 <= rectCells.left || rectCells.right + 1 <= _rowLeft[y], false); } } // Invalidate the space taken up by the new sprite for (int y = rectCells.top; y < rectCells.bottom; y++) { if (y >= 0 && y < _size.y / s_gridSize && y < _countof(_rowRight)) { if (_rowRight[y]) { _rowLeft[y] = std::min<BYTE>(_rowLeft[y], rectCells.left); _rowRight[y] = std::max<BYTE>(_rowRight[y], rectCells.right); } else { _rowLeft[y] = rectCells.left; _rowRight[y] = rectCells.right; } } } return true; }
ff::ComPtr<ff::ICommandRouter> ff::ViewWindow::CreateCommandRouter() { ComPtr<ICommandRouter> router; assertRetVal(ff::CreateNullCommandRouter(&router), ComPtr<ICommandRouter>()); return router; }
static bool ConvertOptimizedTextures( DXGI_FORMAT format, size_t mipMapLevels, ff::Vector<ff::ComPtr<ff::IGraphTexture>> &textures, ff::Vector<ff::ComPtr<ff::IGraphTexture>> &finalTextures, ff::Vector<std::shared_ptr<DirectX::ScratchImage>> &alphaTextures) { for (size_t i = 0; i < textures.Size(); i++) { ff::IGraphTexture *texture = textures[i]; ff::IGraphDevice *device = texture->GetDevice(); ff::ComPtr<ff::IGraphTexture> newTexture; assertRetVal(texture->Convert(format, mipMapLevels, &newTexture), false); finalTextures.Push(newTexture); DirectX::ScratchImage scratch; assertHrRetVal(DirectX::CaptureTexture(device->Get3d(), device->GetContext(), texture->GetTexture(), scratch), false); std::shared_ptr<DirectX::ScratchImage> alphaScratch = std::make_shared<DirectX::ScratchImage>(); assertHrRetVal(DirectX::Convert(scratch.GetImages(), 1, scratch.GetMetadata(), DXGI_FORMAT_A8_UNORM, DirectX::TEX_FILTER_DEFAULT, 0, *alphaScratch), false); alphaTextures.Push(alphaScratch); } return true; }
bool ff::Value::CreateGuid(REFGUID guid, Value **ppValue) { assertRetVal(ppValue, false); if (guid != GUID_NULL) { *ppValue = NewValueOneRef(); (*ppValue)->SetType(Type::Guid); (*ppValue)->_guid = guid; } else { static Value::StaticValue s_data; static Value *s_val = nullptr; if (!s_val) { ScopeStaticValueAlloc scopeAlloc; if (!s_val) { s_val = s_data.AsValue(); s_val->Value::Value(); s_val->SetType(Type::Guid); s_val->_guid = GUID_NULL; } } *ppValue = s_val; } return true; }
ff::String ff::SmallDict::KeyAt(size_t index) const { assertRetVal(index < Size(), ff::GetEmptyString()); hash_t hash = _data->entries[index].hash; return _data->atomizer->GetString(hash); }
bool ff::Value::CreateRectF(const RectFloat &rect, Value **ppValue) { assertRetVal(ppValue, false); if (!rect.IsNull()) { *ppValue = NewValueOneRef(); (*ppValue)->SetType(Type::RectF); (*ppValue)->InternalGetRectF() = rect; } else { static Value::StaticValue s_data; static Value *s_val = nullptr; if (!s_val) { ScopeStaticValueAlloc scopeAlloc; if (!s_val) { s_val = s_data.AsValue(); s_val->Value::Value(); s_val->SetType(Type::RectF); s_val->InternalGetRectF().SetRect(0, 0, 0, 0); } } *ppValue = s_val; } return true; }
bool ff::Value::CreateString(StringRef str, Value **ppValue) { assertRetVal(ppValue, false); if (!str.length()) { static Value::StaticValue s_data; static Value *s_val = nullptr; if (!s_val) { ScopeStaticValueAlloc scopeAlloc; if (!s_val) { s_val = s_data.AsValue(); s_val->Value::Value(); s_val->SetType(Type::String); s_val->InternalGetString().String::String(); } } *ppValue = s_val; } else { *ppValue = NewValueOneRef(); (*ppValue)->SetType(Type::String); (*ppValue)->InternalGetString().String::String(str); } return true; }
bool ff::Value::CreateObject(IUnknown *pObj, Value **ppValue) { assertRetVal(ppValue, false); if (pObj) { *ppValue = NewValueOneRef(); (*ppValue)->SetType(Type::Object); (*ppValue)->_object = GetAddRef(pObj); } else { static Value::StaticValue s_data; static Value *s_val = nullptr; if (!s_val) { ScopeStaticValueAlloc scopeAlloc; if (!s_val) { s_val = s_data.AsValue(); s_val->Value::Value(); s_val->SetType(Type::Object); s_val->_object = nullptr; } } *ppValue = s_val; } return true; }
bool ff::EntityDomain::DeleteComponent(Entity entity, ComponentFactoryEntry *factoryEntry) { assertRetVal(factoryEntry, false); EntityEntry *entityEntry = EntityEntry::FromEntity(entity); size_t i = (entityEntry->_componentBits & factoryEntry->_bit) != 0 ? entityEntry->_components.Find(factoryEntry) : INVALID_SIZE; if (i != INVALID_SIZE) { UnregisterEntityWithSystems(entityEntry, factoryEntry); verify(factoryEntry->_factory->Delete(entity)); entityEntry->_components.Delete(i); entityEntry->_componentBits = 0; for (ComponentFactoryEntry *factoryEntry: entityEntry->_components) { entityEntry->_componentBits |= factoryEntry->_bit; } return true; } return false; }
bool ff::Value::CreateBool(bool val, Value **ppValue) { assertRetVal(ppValue, false); static Value::StaticValue s_data[2]; static bool s_init = false; if (!s_init) { ScopeStaticValueAlloc scopeAlloc; if (!s_init) { Value *pVal = s_data[0].AsValue(); pVal->Value::Value(); pVal->SetType(Type::Bool); pVal->_bool = false; pVal = s_data[1].AsValue(); pVal->Value::Value(); pVal->SetType(Type::Bool); pVal->_bool = true; s_init = true; } } *ppValue = s_data[val ? 1 : 0].AsValue(); return true; }
bool ff::Value::CreateFloat(float val, Value **ppValue) { assertRetVal(ppValue, false); if (val) { *ppValue = NewValueOneRef(); (*ppValue)->SetType(Type::Float); (*ppValue)->_float = val; } else { static Value::StaticValue s_data; static Value *s_val = nullptr; if (!s_val) { ScopeStaticValueAlloc scopeAlloc; if (!s_val) { s_val = s_data.AsValue(); s_val->Value::Value(); s_val->SetType(Type::Float); s_val->_float = 0; } } *ppValue = s_val; } return true; }
bool ff::ViewWindow::Deactivate(bool hide) { assertRetVal(IsValid(), true); if (_active) { _active = false; #if !METRO_APP if (hide) { SetWindowPos(Handle(), HWND_TOP, RectInt(0, 0, 0, 0), SWP_HIDEWINDOW | SWP_NOOWNERZORDER); } if (_mainWindow != nullptr) { HWND child = GetChildWindow(); if (child && ff::IsAncestor(child, Handle())) { _mainWindow->HideSharedViewTarget(); } } #endif OnDeactivated(); } return true; }
bool ff::Value::CreatePointF(const PointFloat &point, Value **ppValue) { assertRetVal(ppValue, false); if (point.x || point.y) { *ppValue = NewValueOneRef(); (*ppValue)->SetType(Type::PointF); (*ppValue)->InternalGetPointF() = point; } else { static Value::StaticValue s_data; static Value *s_val = nullptr; if (!s_val) { ScopeStaticValueAlloc scopeAlloc; if (!s_val) { s_val = s_data.AsValue(); s_val->Value::Value(); s_val->SetType(Type::PointF); s_val->InternalGetPointF().SetPoint(0, 0); } } *ppValue = s_val; } return true; }
bool ff::SaveBytes(IDataWriter *pWriter, const void *pMem, size_t nBytes) { assertRetVal(pWriter, false); assertRetVal(pWriter->Write(pMem, nBytes), false); // Make sure that the data size is a multiple of 32 bits // STATIC_DATA (pod) static const BYTE padding[4] = { 0, 0, 0, 0 }; size_t nPadding = RoundUpTo4(nBytes) - nBytes; if (nPadding) { assertRetVal(pWriter->Write(padding, nPadding), false); } return true; }
bool ff::SaveData<ff::String>(ff::IDataWriter *pWriter, ff::StringRef data) { DWORD nBytes = (DWORD)((data.length() + 1) * sizeof(wchar_t)); assertRetVal(SaveData(pWriter, nBytes), false); return SaveBytes(pWriter, data.c_str(), nBytes); }
bool ff::LoadBytes(IDataReader *pReader, size_t nBytes, IData **ppData) { assertRetVal(pReader, false); ComPtr<IData> pData; size_t nNewPos = std::min(pReader->GetSize(), pReader->GetPos() + RoundUpTo4(nBytes)); assertRetVal(pReader->Read(nBytes, ppData ? &pData : nullptr), false); assertRetVal(pReader->SetPos(nNewPos), false); if (ppData) { *ppData = pData.Detach(); } return true; }
bool ff::WriteUnicodeBOM(IDataWriter *pWriter) { assertRetVal(pWriter, false); WORD bom = 0xFEFF; return pWriter->Write(&bom, sizeof(bom)); }
ff::Component *ff::EntityDomain::CloneComponent(Entity entity, Entity sourceEntity, ComponentFactoryEntry *factoryEntry) { assertRetVal(factoryEntry, nullptr); Component *component = LookupComponent(entity, factoryEntry); assertRetVal(component == nullptr, component); component = factoryEntry->_factory->Clone(entity, sourceEntity); EntityEntry *entityEntry = EntityEntry::FromEntity(entity); assert(entityEntry->_components.Find(factoryEntry) == INVALID_SIZE); entityEntry->_componentBits |= factoryEntry->_bit; entityEntry->_components.Push(factoryEntry); RegisterEntityWithSystems(entityEntry, factoryEntry); return component; }
bool ff::WriteUnicodeBOMToFile(HANDLE hFile) { assertRetVal(hFile, false); WORD bom = 0xFEFF; return WriteFile(hFile, &bom, sizeof(bom)); }
size_t ff::SetFilePointerToEnd(HANDLE hFile) { assertRetVal(hFile, INVALID_SIZE); LARGE_INTEGER cur; LARGE_INTEGER move; move.QuadPart = 0; assertRetVal(::SetFilePointerEx(hFile, move, &cur, FILE_END), INVALID_SIZE); #ifdef _WIN64 return cur.QuadPart; #else assertRetVal(!cur.HighPart, INVALID_SIZE); return cur.LowPart; #endif }
bool ff::BufferCache::CreateBuffer(size_t nBytes, ID3D11Buffer **ppBuffer) { assertRetVal(nBytes && ppBuffer && _device && _device->GetDX(), false); D3D11_BUFFER_DESC desc; ZeroObject(desc); desc.ByteWidth = (UINT)nBytes; desc.Usage = D3D11_USAGE_DYNAMIC; desc.BindFlags = _binding; desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; assertRetVal(SUCCEEDED(_device->GetDX()->CreateBuffer(&desc, nullptr, ppBuffer)), false); assertRetVal(*ppBuffer, false); return true; }
ff::INativeHostControl *ff::ClrStartup(StringRef versionOrAssembly) { // Use my own empty config file ComPtr<IDataFile> configFile; assertRetVal(GetAppConfig(&configFile), false); return ClrStartup(configFile->GetPath(), versionOrAssembly); }
bool ff::OptimizeSprites(ISpriteList *pSprites, DXGI_FORMAT format, size_t nMipMapLevels, ISpriteList **ppOptimizedSprites) { assertRetVal(pSprites && ppOptimizedSprites, false); // Create the return value ComPtr<ISpriteList> pNewSprites; assertRetVal(CreateSpriteList(pSprites->GetDevice(), &pNewSprites), false); // Cache all the sprites Vector<OptimizedSpriteInfo> sprites; sprites.Reserve(pSprites->GetCount()); for (size_t i = 0; i < pSprites->GetCount(); i++) { OptimizedSpriteInfo sprite(pSprites->Get(i), i); sprites.Push(sprite); } // Sort the sprites by size if (!sprites.IsEmpty()) { qsort(sprites.Data(), sprites.Size(), sizeof(OptimizedSpriteInfo), CompareSpriteInfo); } // Figure out how many textures to create Vector<OptimizedTextureInfo> textureInfos; Vector<ComPtr<IGraphTexture>> textures; Vector<ComPtr<IGraphTexture>> finalTextures; Vector<std::shared_ptr<DirectX::ScratchImage>> alphaTextures; assertRetVal(ComputeOptimizedSprites(sprites, textureInfos), false); assertRetVal(CreateOptimizedTextures(format, pSprites->GetDevice(), textureInfos, textures), false); if (!sprites.IsEmpty()) { qsort(sprites.Data(), sprites.Size(), sizeof(OptimizedSpriteInfo), CompareSpriteInfoIndex); } assertRetVal(CopyOptimizedSprites(sprites, textures), false); assertRetVal(ConvertOptimizedTextures(format, nMipMapLevels, textures, finalTextures, alphaTextures), false); // Create final sprites for (size_t i = 0; i < sprites.Size(); i++) { OptimizedSpriteInfo &sprite = sprites[i]; const SpriteData &data = sprite._sprite->GetSpriteData(); SpriteType type = UpdateSpriteType(sprite, *alphaTextures[sprite._destTexture]); assertRetVal(pNewSprites->Add( finalTextures[sprite._destTexture], data._name, sprite._destRect.ToFloat(), sprite._srcHandle, sprite._srcScale, type), false); } *ppOptimizedSprites = pNewSprites.Detach(); return true; }
ff::ValuePtr TextureTransformValue(ff::StringRef name, const ff::Dict &input) { ff::String fileProp = input.GetString(PROP_FILE); size_t mipsProp = input.GetSize(PROP_MIPS, 1); ff::String formatProp = input.GetString(PROP_FORMAT, ff::String(L"rgba32")); DXGI_FORMAT format = ff::ParseTextureFormat(formatProp); assertRetVal(fileProp.size() && format != DXGI_FORMAT_UNKNOWN, nullptr); ff::String basePath = input.GetString(RES_BASE); ff::String fullFile = basePath; ff::AppendPathTail(fullFile, fileProp); ff::ComPtr<IUnknown> catParent = ff::ProcessGlobals::Get()->GetModules().CreateParentForCategory(ff::GetCategoryGraphicsObject(), nullptr); ff::ComPtr<ff::IGraphDevice> graph; assertRetVal(graph.QueryFrom(catParent), nullptr); ff::ComPtr<ff::IGraphTexture> texture; assertRetVal(ff::CreateGraphTexture(graph, fullFile, format, mipsProp, &texture), nullptr); ff::ComPtr<ff::IResourceSave> resourceSave; assertRetVal(resourceSave.QueryFrom(texture), nullptr); ff::Dict textureSave; assertRetVal(resourceSave->SaveResource(textureSave), nullptr); ff::ComPtr<ff::IData> textureData = textureSave.GetData(PROP_DATA); assertRetVal(textureData, nullptr); ff::ValuePtr outputValue; assertRetVal(ff::Value::CreateData(textureData, &outputValue), nullptr); return outputValue; }
bool ff::ViewWindow::Create(PWND parent, ViewType type) { assertRetVal(parent, false); _viewType = type; #if !METRO_APP ff::String viewName = String::from_acp(typeid(*this).name() + 6); // skip "class " assertRetVal(CreateBlank(viewName, parent, WS_CHILD), false); _allowLayout = true; #endif assertRetVal((_commandRouter = CreateCommandRouter()) != nullptr, false); assertRetVal(Initialize(), false); // Don't do Layout() until the view is activated return true; }
bool ff::LoadBytes(IDataReader *pReader, void *pMem, size_t nBytes) { const BYTE* pData = LoadBytes(pReader, nBytes); assertRetVal(pData && pMem, false); CopyMemory(pMem, pData, nBytes); return true; }
bool ff::EntityDomain::AddSystem(std::shared_ptr<EntitySystemBase> system) { assertRetVal(system != nullptr && system->GetDomain() == this, false); SystemEntry &systemEntry = _systems.Insert(); SetSystem(systemEntry, system); return true; }
ff::Component *ff::EntityDomain::LookupComponent(Entity entity, ComponentFactoryEntry *factoryEntry) { assertRetVal(factoryEntry, nullptr); EntityEntry *entityEntry = EntityEntry::FromEntity(entity); return ((entityEntry->_componentBits & factoryEntry->_bit) != 0) ? factoryEntry->_factory->Lookup(entity) : nullptr; }
ff::RectFloat ff::SpriteData::GetTextureRectF() const { assertRetVal(_texture, RectFloat(0, 0, 0, 0)); PointFloat texSize = _texture->GetSize().ToFloat(); RectFloat texRect = _textureUV * texSize; texRect.Normalize(); return texRect; }
bool ff::Value::CreateSavedDict(ff::ISavedData *data, Value **ppValue) { assertRetVal(data && ppValue, false); *ppValue = NewValueOneRef(); (*ppValue)->SetType(Type::SavedDict); (*ppValue)->_savedData = ff::GetAddRef(data); return true; }