void ProjectionEditor::mouseDragged(ofMouseEventArgs& args) { ofVec2f mousePosition = ofVec2f(args.x, args.y); // Collect all vertices of the projection surfaces vector<ofVec3f*> allVertices; for (int i = 0; i < surfaceManager->size(); i++) { BaseSurface* surface = surfaceManager->getSurface(i); if (surface == surfaceManager->getSelectedSurface()) { continue; // Don't add vertices of selected surface } for (int j = 0; j < surface->getVertices().size(); j++) { allVertices.push_back(&surface->getVertices()[j]); } } // Snap currently dragged joint to nearest vertex for (int i = 0; i < joints.size(); i++) { if (joints[i]->isDragged()) { // Snap it! for (int j = 0; j < allVertices.size(); j++) { float distance = mousePosition.distance(*allVertices[j]); // cout << "distance: " << distance << endl; if (distance < fSnapDistance) { joints[i]->position = *allVertices[j]; ofVec2f clickDistance = joints[i]->position - ofVec2f(args.x, args.y); joints[i]->setClickDistance(clickDistance); break; } } } } }
BaseSurface *BaseSurfaceStorage::addSurface(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime, bool keepLoaded) { for (uint32 i = 0; i < _surfaces.size(); i++) { if (scumm_stricmp(_surfaces[i]->getFileName(), filename.c_str()) == 0) { _surfaces[i]->_referenceCount++; return _surfaces[i]; } } if (!BaseFileManager::getEngineInstance()->hasFile(filename)) { if (filename.size()) { _gameRef->LOG(0, "Missing image: '%s'", filename.c_str()); } if (_gameRef->_debugDebugMode) { return addSurface("invalid_debug.bmp", defaultCK, ckRed, ckGreen, ckBlue, lifeTime, keepLoaded); } else { return addSurface("invalid.bmp", defaultCK, ckRed, ckGreen, ckBlue, lifeTime, keepLoaded); } } BaseSurface *surface; surface = _gameRef->_renderer->createSurface(); if (!surface) { return NULL; } if (DID_FAIL(surface->create(filename, defaultCK, ckRed, ckGreen, ckBlue, lifeTime, keepLoaded))) { delete surface; return NULL; } else { surface->_referenceCount = 1; _surfaces.push_back(surface); return surface; } }
void BaseSurface::flipHorizontal(BaseSurface &dest) { dest.create(this->w, this->h); for (int y = 0; y < h; ++y) { const byte *pSrc = (const byte *)getBasePtr(this->w - 1, y); byte *pDest = (byte *)dest.getBasePtr(0, y); for (int x = 0; x < w; ++x, --pSrc, ++pDest) *pDest = *pSrc; } }
BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset) { //TextLineList lines; // TODO: Use WideString-conversion here. //WrapText(text, width, maxHeight, lines); Common::Array<Common::String> lines; _font->wordWrapText(text, width, lines); while (maxHeight > 0 && lines.size() * _lineHeight > maxHeight) { lines.pop_back(); } if (lines.size() == 0) { return nullptr; } Graphics::TextAlign alignment = Graphics::kTextAlignInvalid; if (align == TAL_LEFT) { alignment = Graphics::kTextAlignLeft; } else if (align == TAL_CENTER) { alignment = Graphics::kTextAlignCenter; } else if (align == TAL_RIGHT) { alignment = Graphics::kTextAlignRight; } debugC(kWintermuteDebugFont, "%s %d %d %d %d", text.c_str(), RGBCOLGetR(_layers[0]->_color), RGBCOLGetG(_layers[0]->_color), RGBCOLGetB(_layers[0]->_color), RGBCOLGetA(_layers[0]->_color)); // void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const; Graphics::Surface *surface = new Graphics::Surface(); if (_deletableFont) { // We actually have a TTF surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24)); } else { // We are using a fallback, they can't do 32bpp surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0)); } uint32 useColor = 0xffffffff; Common::Array<Common::String>::iterator it; int heightOffset = 0; for (it = lines.begin(); it != lines.end(); ++it) { _font->drawString(surface, *it, 0, heightOffset, width, useColor, alignment); heightOffset += (int)_lineHeight; } BaseSurface *retSurface = _gameRef->_renderer->createSurface(); Graphics::Surface *convertedSurface = surface->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24)); retSurface->putSurface(*convertedSurface, true); convertedSurface->free(); surface->free(); delete surface; delete convertedSurface; return retSurface; // TODO: _isUnderline, _isBold, _isItalic, _isStriked }
BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset) { //TextLineList lines; // TODO: Use WideString-conversion here. //WrapText(text, width, maxHeight, lines); Common::Array<WideString> lines; _font->wordWrapText(text, width, lines); while (maxHeight > 0 && lines.size() * _lineHeight > maxHeight) { lines.pop_back(); } if (lines.size() == 0) { return nullptr; } Graphics::TextAlign alignment = Graphics::kTextAlignInvalid; if (align == TAL_LEFT) { alignment = Graphics::kTextAlignLeft; } else if (align == TAL_CENTER) { alignment = Graphics::kTextAlignCenter; } else if (align == TAL_RIGHT) { alignment = Graphics::kTextAlignRight; } // TODO: This debug call does not work with WideString because text.c_str() returns an uint32 array. //debugC(kWintermuteDebugFont, "%s %d %d %d %d", text.c_str(), RGBCOLGetR(_layers[0]->_color), RGBCOLGetG(_layers[0]->_color), RGBCOLGetB(_layers[0]->_color), RGBCOLGetA(_layers[0]->_color)); // void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const; Graphics::Surface *surface = new Graphics::Surface(); surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), _gameRef->_renderer->getPixelFormat()); uint32 useColor = 0xffffffff; Common::Array<WideString>::iterator it; int heightOffset = 0; for (it = lines.begin(); it != lines.end(); ++it) { _font->drawString(surface, *it, 0, heightOffset, width, useColor, alignment); heightOffset += (int)_lineHeight; } BaseSurface *retSurface = _gameRef->_renderer->createSurface(); if (_deletableFont) { // Reconstruct the alpha channel of the font. // Since we painted it with color 0xFFFFFFFF onto a black background, // the alpha channel is gone, but the color value of each pixel corresponds // to its original alpha value. Graphics::PixelFormat format = _gameRef->_renderer->getPixelFormat(); uint32 *pixels = (uint32 *)surface->getPixels(); // This is a Surface we created ourselves, so no empty space between rows. for (int i = 0; i < surface->w * surface->h; ++i) { uint8 a, r, g, b; format.colorToRGB(*pixels, r, g, b); a = r; *pixels++ = format.ARGBToColor(a, r, g, b); } } retSurface->putSurface(*surface, true); surface->free(); delete surface; return retSurface; // TODO: _isUnderline, _isBold, _isItalic, _isStriked }
void BaseFontTT::drawText(const byte *text, int x, int y, int width, TTextAlign align, int maxHeight, int maxLength) { if (text == nullptr || strcmp((const char *)text, "") == 0) { return; } WideString textStr; // TODO: Why do we still insist on Widestrings everywhere? // HACK: J.U.L.I.A. uses CP1252, we need to fix that, // And we still don't have any UTF8-support. if (_gameRef->_textEncoding == TEXT_UTF8) { textStr = StringUtil::utf8ToWide((const char *)text); } else { textStr = StringUtil::ansiToWide((const char *)text); } if (maxLength >= 0 && textStr.size() > (uint32)maxLength) { textStr = WideString(textStr.c_str(), (uint32)maxLength); } //text = text.substr(0, MaxLength); // TODO: Remove BaseRenderer *renderer = _gameRef->_renderer; // find cached surface, if exists uint32 minUseTime = UINT_MAX; int minIndex = -1; BaseSurface *surface = nullptr; int textOffset = 0; for (int i = 0; i < NUM_CACHED_TEXTS; i++) { if (_cachedTexts[i] == nullptr) { minUseTime = 0; minIndex = i; } else { if (_cachedTexts[i]->_text == textStr && _cachedTexts[i]->_align == align && _cachedTexts[i]->_width == width && _cachedTexts[i]->_maxHeight == maxHeight && _cachedTexts[i]->_maxLength == maxLength) { surface = _cachedTexts[i]->_surface; textOffset = _cachedTexts[i]->_textOffset; _cachedTexts[i]->_marked = true; _cachedTexts[i]->_lastUsed = g_system->getMillis(); break; } else { if (_cachedTexts[i]->_lastUsed < minUseTime) { minUseTime = _cachedTexts[i]->_lastUsed; minIndex = i; } } } } // not found, create one if (!surface) { debugC(kWintermuteDebugFont, "Draw text: %s", text); surface = renderTextToTexture(textStr, width, align, maxHeight, textOffset); if (surface) { // write surface to cache if (_cachedTexts[minIndex] != nullptr) { delete _cachedTexts[minIndex]; } _cachedTexts[minIndex] = new BaseCachedTTFontText; _cachedTexts[minIndex]->_surface = surface; _cachedTexts[minIndex]->_align = align; _cachedTexts[minIndex]->_width = width; _cachedTexts[minIndex]->_maxHeight = maxHeight; _cachedTexts[minIndex]->_maxLength = maxLength; _cachedTexts[minIndex]->_text = textStr; _cachedTexts[minIndex]->_textOffset = textOffset; _cachedTexts[minIndex]->_marked = true; _cachedTexts[minIndex]->_lastUsed = g_system->getMillis(); } } // and paint it if (surface) { Rect32 rc; rc.setRect(0, 0, surface->getWidth(), surface->getHeight()); for (uint32 i = 0; i < _layers.size(); i++) { uint32 color = _layers[i]->_color; uint32 origForceAlpha = renderer->_forceAlphaColor; if (renderer->_forceAlphaColor != 0) { color = BYTETORGBA(RGBCOLGetR(color), RGBCOLGetG(color), RGBCOLGetB(color), RGBCOLGetA(renderer->_forceAlphaColor)); renderer->_forceAlphaColor = 0; } surface->displayTransOffset(x, y - textOffset, rc, color, Graphics::BLEND_NORMAL, false, false, _layers[i]->_offsetX, _layers[i]->_offsetY); renderer->_forceAlphaColor = origForceAlpha; } } }