コード例 #1
0
ファイル: cursor32.cpp プロジェクト: fedor4ever/scummvm
void GfxCursor32::setRestrictedArea(const Common::Rect &rect) {
    _restrictedArea = rect;

    const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
    const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;
    const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
    const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;

    mulru(_restrictedArea, Ratio(screenWidth, scriptWidth), Ratio(screenHeight, scriptHeight), 0);

    if (_position.x < rect.left) {
        _position.x = rect.left;
    }
    if (_position.x >= rect.right) {
        _position.x = rect.right - 1;
    }
    if (_position.y < rect.top) {
        _position.y = rect.top;
    }
    if (_position.y >= rect.bottom) {
        _position.y = rect.bottom - 1;
    }

    g_system->warpMouse(_position.x, _position.y);
}
コード例 #2
0
ファイル: kgraphics32.cpp プロジェクト: bSr43/scummvm
reg_t kCelWide32(EngineState *s, int argc, reg_t *argv) {
	GuiResourceId resourceId = argv[0].toUint16();
	int16 loopNo = argv[1].toSint16();
	int16 celNo = argv[2].toSint16();
	CelObjView celObj(resourceId, loopNo, celNo);
	return make_reg(0, mulru(celObj._width, Ratio(g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth, celObj._scaledWidth)));
}
コード例 #3
0
ファイル: screen_item32.cpp プロジェクト: bSr43/scummvm
void ScreenItem::calcRects(const Plane &plane) {
	const int16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
	const int16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;
	const int16 screenWidth = g_sci->_gfxFrameout->getCurrentBuffer().screenWidth;
	const int16 screenHeight = g_sci->_gfxFrameout->getCurrentBuffer().screenHeight;

	const CelObj &celObj = getCelObj();

	Common::Rect celRect(celObj._width, celObj._height);
	if (_useInsetRect) {
		if (_insetRect.intersects(celRect)) {
			_insetRect.clip(celRect);
		} else {
			_insetRect = Common::Rect();
		}
	} else {
		_insetRect = celRect;
	}

	Ratio scaleX, scaleY;

	if (_scale.signal & kScaleSignalDoScaling32) {
		if (_scale.signal & kScaleSignalUseVanishingPoint) {
			int num = _scale.max * (_position.y - plane._vanishingPoint.y) / (scriptWidth - plane._vanishingPoint.y);
			scaleX = Ratio(num, 128);
			scaleY = Ratio(num, 128);
		} else {
			scaleX = Ratio(_scale.x, 128);
			scaleY = Ratio(_scale.y, 128);
		}
	}

	if (scaleX.getNumerator() && scaleY.getNumerator()) {
		_screenItemRect = _insetRect;

		const Ratio celToScreenX(screenWidth, celObj._scaledWidth);
		const Ratio celToScreenY(screenHeight, celObj._scaledHeight);

		// Cel may use a coordinate system that is not the same size as the
		// script coordinate system (usually this means high-resolution
		// pictures with low-resolution scripts)
		if (celObj._scaledWidth != kLowResX || celObj._scaledHeight != kLowResY) {
			// high resolution coordinates

			if (_useInsetRect) {
				const Ratio scriptToCelX(celObj._scaledWidth, scriptWidth);
				const Ratio scriptToCelY(celObj._scaledHeight, scriptHeight);
				mulru(_screenItemRect, scriptToCelX, scriptToCelY, 0);

				if (_screenItemRect.intersects(celRect)) {
					_screenItemRect.clip(celRect);
				} else {
					_screenItemRect = Common::Rect();
				}
			}

			int displaceX = celObj._displace.x;
			int displaceY = celObj._displace.y;

			if (_mirrorX != celObj._mirrorX && _celInfo.type != kCelTypePic) {
				displaceX = celObj._width - celObj._displace.x - 1;
			}

			if (!scaleX.isOne() || !scaleY.isOne()) {
				// Different games use a different cel scaling mode, but the
				// difference isn't consistent across SCI versions; instead,
				// it seems to be related to an update that happened during
				// SCI2.1mid where games started using hi-resolution game
				// scripts
				if (scriptWidth == kLowResX) {
					mulinc(_screenItemRect, scaleX, scaleY);
				} else {
					_screenItemRect.left = (_screenItemRect.left * scaleX).toInt();
					_screenItemRect.top = (_screenItemRect.top * scaleY).toInt();

					if (scaleX.getNumerator() > scaleX.getDenominator()) {
						_screenItemRect.right = (_screenItemRect.right * scaleX).toInt();
					} else {
						_screenItemRect.right = ((_screenItemRect.right - 1) * scaleX).toInt() + 1;
					}

					if (scaleY.getNumerator() > scaleY.getDenominator()) {
						_screenItemRect.bottom = (_screenItemRect.bottom * scaleY).toInt();
					} else {
						_screenItemRect.bottom = ((_screenItemRect.bottom - 1) * scaleY).toInt() + 1;
					}
				}

				displaceX = (displaceX * scaleX).toInt();
				displaceY = (displaceY * scaleY).toInt();
			}

			mulinc(_screenItemRect, celToScreenX, celToScreenY);
			displaceX = (displaceX * celToScreenX).toInt();
			displaceY = (displaceY * celToScreenY).toInt();

			const Ratio scriptToScreenX = Ratio(screenWidth, scriptWidth);
			const Ratio scriptToScreenY = Ratio(screenHeight, scriptHeight);

			if (/* TODO: dword_C6288 */ false && _celInfo.type == kCelTypePic) {
				_scaledPosition.x = _position.x;
				_scaledPosition.y = _position.y;
			} else {
				_scaledPosition.x = (_position.x * scriptToScreenX).toInt() - displaceX;
				_scaledPosition.y = (_position.y * scriptToScreenY).toInt() - displaceY;
			}

			_screenItemRect.translate(_scaledPosition.x, _scaledPosition.y);

			if (_mirrorX != celObj._mirrorX && _celInfo.type == kCelTypePic) {
				Common::Rect temp(_insetRect);

				if (!scaleX.isOne()) {
					mulinc(temp, scaleX, Ratio());
				}

				mulinc(temp, celToScreenX, Ratio());

				CelObjPic *celObjPic = dynamic_cast<CelObjPic *>(_celObj);
				if (celObjPic == nullptr) {
					error("Expected a CelObjPic");
				}
				temp.translate((celObjPic->_relativePosition.x * scriptToScreenX).toInt() - displaceX, 0);

				// TODO: This is weird.
				int deltaX = plane._planeRect.width() - temp.right - 1 - temp.left;

				_scaledPosition.x += deltaX;
				_screenItemRect.translate(deltaX, 0);
			}

			_scaledPosition.x += plane._planeRect.left;
			_scaledPosition.y += plane._planeRect.top;
			_screenItemRect.translate(plane._planeRect.left, plane._planeRect.top);

			_ratioX = scaleX * celToScreenX;
			_ratioY = scaleY * celToScreenY;
		} else {
			// low resolution coordinates

			int displaceX = celObj._displace.x;
			if (_mirrorX != celObj._mirrorX && _celInfo.type != kCelTypePic) {
				displaceX = celObj._width - celObj._displace.x - 1;
			}

			if (!scaleX.isOne() || !scaleY.isOne()) {
				mulinc(_screenItemRect, scaleX, scaleY);
				// TODO: This was in the original code, baked into the
				// multiplication though it is not immediately clear
				// why this is the only one that reduces the BR corner
				_screenItemRect.right -= 1;
				_screenItemRect.bottom -= 1;
			}

			_scaledPosition.x = _position.x - (displaceX * scaleX).toInt();
			_scaledPosition.y = _position.y - (celObj._displace.y * scaleY).toInt();
			_screenItemRect.translate(_scaledPosition.x, _scaledPosition.y);

			if (_mirrorX != celObj._mirrorX && _celInfo.type == kCelTypePic) {
				Common::Rect temp(_insetRect);

				if (!scaleX.isOne()) {
					mulinc(temp, scaleX, Ratio());
					temp.right -= 1;
				}

				CelObjPic *celObjPic = dynamic_cast<CelObjPic *>(_celObj);
				if (celObjPic == nullptr) {
					error("Expected a CelObjPic");
				}
				temp.translate(celObjPic->_relativePosition.x - (displaceX * scaleX).toInt(), celObjPic->_relativePosition.y - (celObj._displace.y * scaleY).toInt());

				// TODO: This is weird.
				int deltaX = plane._gameRect.width() - temp.right - 1 - temp.left;

				_scaledPosition.x += deltaX;
				_screenItemRect.translate(deltaX, 0);
			}

			_scaledPosition.x += plane._gameRect.left;
			_scaledPosition.y += plane._gameRect.top;
			_screenItemRect.translate(plane._gameRect.left, plane._gameRect.top);

			if (celObj._scaledWidth != screenWidth || celObj._scaledHeight != screenHeight) {
				mulru(_scaledPosition, celToScreenX, celToScreenY);
				mulru(_screenItemRect, celToScreenX, celToScreenY, 1);
			}

			_ratioX = scaleX * celToScreenX;
			_ratioY = scaleY * celToScreenY;
		}

		_screenRect = _screenItemRect;

		if (_screenRect.intersects(plane._screenRect)) {
			_screenRect.clip(plane._screenRect);
		} else {
			_screenRect.right = 0;
			_screenRect.bottom = 0;
			_screenRect.left = 0;
			_screenRect.top = 0;
		}

		if (!_fixedPriority) {
			_priority = _z + _position.y;
		}
	} else {
		_screenRect.left = 0;
		_screenRect.top = 0;
		_screenRect.right = 0;
		_screenRect.bottom = 0;
	}
}
コード例 #4
0
ファイル: screen_item32.cpp プロジェクト: bSr43/scummvm
Common::Rect ScreenItem::getNowSeenRect(const Plane &plane) const {
	CelObj &celObj = getCelObj();

	Common::Rect celObjRect(celObj._width, celObj._height);
	Common::Rect nsRect;

	if (_useInsetRect) {
		if (_insetRect.intersects(celObjRect)) {
			nsRect = _insetRect;
			nsRect.clip(celObjRect);
		} else {
			nsRect = Common::Rect();
		}
	} else {
		nsRect = celObjRect;
	}

	const uint16 scriptWidth = g_sci->_gfxFrameout->getCurrentBuffer().scriptWidth;
	const uint16 scriptHeight = g_sci->_gfxFrameout->getCurrentBuffer().scriptHeight;

	Ratio scaleX, scaleY;
	if (_scale.signal & kScaleSignalDoScaling32) {
		if (_scale.signal & kScaleSignalUseVanishingPoint) {
			int num = _scale.max * (_position.y - plane._vanishingPoint.y) / (scriptWidth - plane._vanishingPoint.y);
			scaleX = Ratio(num, 128);
			scaleY = Ratio(num, 128);
		} else {
			scaleX = Ratio(_scale.x, 128);
			scaleY = Ratio(_scale.y, 128);
		}
	}

	if (scaleX.getNumerator() == 0 || scaleY.getNumerator() == 0) {
		return Common::Rect();
	}

	int16 displaceX = celObj._displace.x;
	int16 displaceY = celObj._displace.y;

	if (_mirrorX != celObj._mirrorX && _celInfo.type != kCelTypePic) {
		displaceX = celObj._width - displaceX - 1;
	}

	if (celObj._scaledWidth != kLowResX || celObj._scaledHeight != kLowResY) {
		// high resolution coordinates

		if (_useInsetRect) {
			Ratio scriptToCelX(celObj._scaledWidth, scriptWidth);
			Ratio scriptToCelY(celObj._scaledHeight, scriptHeight);
			mulru(nsRect, scriptToCelX, scriptToCelY, 0);

			if (nsRect.intersects(celObjRect)) {
				nsRect.clip(celObjRect);
			} else {
				nsRect = Common::Rect();
			}
		}

		if (!scaleX.isOne() || !scaleY.isOne()) {
			// Different games use a different cel scaling mode, but the
			// difference isn't consistent across SCI versions; instead,
			// it seems to be related to an update that happened during
			// SCI2.1mid where games started using hi-resolution game
			// scripts
			if (scriptWidth == kLowResX) {
				mulinc(nsRect, scaleX, scaleY);
				// TODO: This was in the original code, baked into the
				// multiplication though it is not immediately clear
				// why this is the only one that reduces the BR corner
				nsRect.right -= 1;
				nsRect.bottom -= 1;
			} else {
				nsRect.left = (nsRect.left * scaleX).toInt();
				nsRect.top = (nsRect.top * scaleY).toInt();

				if (scaleX.getNumerator() > scaleX.getDenominator()) {
					nsRect.right = (nsRect.right * scaleX).toInt();
				} else {
					nsRect.right = ((nsRect.right - 1) * scaleX).toInt() + 1;
				}

				if (scaleY.getNumerator() > scaleY.getDenominator()) {
					nsRect.bottom = (nsRect.bottom * scaleY).toInt();
				} else {
					nsRect.bottom = ((nsRect.bottom - 1) * scaleY).toInt() + 1;
				}
			}
		}

		Ratio celToScriptX(scriptWidth, celObj._scaledWidth);
		Ratio celToScriptY(scriptHeight, celObj._scaledHeight);

		displaceX = (displaceX * scaleX * celToScriptX).toInt();
		displaceY = (displaceY * scaleY * celToScriptY).toInt();

		mulinc(nsRect, celToScriptX, celToScriptY);
		nsRect.translate(_position.x - displaceX, _position.y - displaceY);
	} else {
		// low resolution coordinates

		if (!scaleX.isOne() || !scaleY.isOne()) {
			mulinc(nsRect, scaleX, scaleY);
			// TODO: This was in the original code, baked into the
			// multiplication though it is not immediately clear
			// why this is the only one that reduces the BR corner
			nsRect.right -= 1;
			nsRect.bottom -= 1;
		}

		displaceX = (displaceX * scaleX).toInt();
		displaceY = (displaceY * scaleY).toInt();
		nsRect.translate(_position.x - displaceX, _position.y - displaceY);

		if (_mirrorX != celObj._mirrorX && _celInfo.type != kCelTypePic) {
			nsRect.translate(plane._gameRect.width() - nsRect.width(), 0);
		}
	}

	return nsRect;
}
コード例 #5
0
ファイル: event.cpp プロジェクト: Cruel/scummvm
SciEvent EventManager::getScummVMEvent() {
#ifdef ENABLE_SCI32
	SciEvent input = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point() };
	SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, Common::Point(), Common::Point() };
#else
	SciEvent input = { SCI_EVENT_NONE, 0, 0, Common::Point() };
	SciEvent noEvent = { SCI_EVENT_NONE, 0, 0, Common::Point() };
#endif

	Common::EventManager *em = g_system->getEventManager();
	Common::Event ev;

	bool found = em->pollEvent(ev);

	// Don't generate events for mouse movement
	while (found && ev.type == Common::EVENT_MOUSEMOVE)
		found = em->pollEvent(ev);

	// Save the mouse position
	//
	// We call getMousePos of the event manager here, since we also want to
	// store the mouse position in case of keyboard events, which do not feature
	// any mouse position information itself.
	// This should be safe, since the mouse position in the event manager should
	// only be updated when a mouse related event has been taken from the queue
	// via pollEvent.
	// We also adjust the position based on the scaling of the screen.
	Common::Point mousePos = em->getMousePos();

#if ENABLE_SCI32
	if (getSciVersion() >= SCI_VERSION_2) {
		Buffer &screen = g_sci->_gfxFrameout->getCurrentBuffer();

		Common::Point mousePosSci = mousePos;
		mulru(mousePosSci, Ratio(screen.scriptWidth, screen.screenWidth), Ratio(screen.scriptHeight, screen.screenHeight));
		noEvent.mousePosSci = input.mousePosSci = mousePosSci;
	} else {
#endif
		g_sci->_gfxScreen->adjustBackUpscaledCoordinates(mousePos.y, mousePos.x);
#if ENABLE_SCI32
	}
#endif

	noEvent.mousePos = input.mousePos = mousePos;

	if (!found || ev.type == Common::EVENT_MOUSEMOVE) {
		int modifiers = em->getModifierState();
		noEvent.modifiers =
			((modifiers & Common::KBD_ALT) ? SCI_KEYMOD_ALT : 0) |
			((modifiers & Common::KBD_CTRL) ? SCI_KEYMOD_CTRL : 0) |
			((modifiers & Common::KBD_SHIFT) ? SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT : 0);

		return noEvent;
	}
	if (ev.type == Common::EVENT_QUIT) {
		input.type = SCI_EVENT_QUIT;
		return input;
	}

	int scummVMKeyFlags;

	switch (ev.type) {
	case Common::EVENT_KEYDOWN:
	case Common::EVENT_KEYUP:
		// Use keyboard modifiers directly in case this is a keyboard event
		scummVMKeyFlags = ev.kbd.flags;
		break;
	default:
		// Otherwise get them from EventManager
		scummVMKeyFlags = em->getModifierState();
		break;
	}

	input.modifiers =
		((scummVMKeyFlags & Common::KBD_ALT) ? SCI_KEYMOD_ALT : 0) |
		((scummVMKeyFlags & Common::KBD_CTRL) ? SCI_KEYMOD_CTRL : 0) |
		((scummVMKeyFlags & Common::KBD_SHIFT) ? SCI_KEYMOD_LSHIFT | SCI_KEYMOD_RSHIFT : 0);
		// Caps lock and Scroll lock have been removed, cause we already handle upper
		// case keys and Scroll lock doesn't seem to be used anywhere
		//((ourModifiers & Common::KBD_CAPS) ? SCI_KEYMOD_CAPSLOCK : 0) |
		//((ourModifiers & Common::KBD_SCRL) ? SCI_KEYMOD_SCRLOCK : 0) |

	// Handle mouse events
	for (int i = 0; i < ARRAYSIZE(mouseEventMappings); i++) {
		if (mouseEventMappings[i].commonType == ev.type) {
			input.type = mouseEventMappings[i].sciType;
			// Sierra passed keyboard modifiers for mouse events, too.

			// Sierra also set certain modifiers within their mouse interrupt handler
			// This whole thing was probably meant for people using a mouse, that only featured 1 button
			// So the user was able to press Ctrl and click the mouse button to create a right click.
			switch (ev.type) {
			case Common::EVENT_RBUTTONDOWN: // right button
			case Common::EVENT_RBUTTONUP:
				input.modifiers |= (SCI_KEYMOD_RSHIFT | SCI_KEYMOD_LSHIFT); // this value was hardcoded in the mouse interrupt handler
				break;
			case Common::EVENT_MBUTTONDOWN: // middle button
			case Common::EVENT_MBUTTONUP:
				input.modifiers |= SCI_KEYMOD_CTRL; // this value was hardcoded in the mouse interrupt handler
				break;
			default:
				break;
			}
			return input;
		}
	}

	// If we reached here, make sure that it's a keydown event
	if (ev.type != Common::EVENT_KEYDOWN)
		return noEvent;

	// Check for Control-Shift-D (debug console)
	if (ev.kbd.hasFlags(Common::KBD_CTRL | Common::KBD_SHIFT) && ev.kbd.keycode == Common::KEYCODE_d) {
		// Open debug console
		Console *con = g_sci->getSciDebugger();
		con->attach();
		return noEvent;
	}

	// Process keyboard events

	bool numlockOn = (ev.kbd.flags & Common::KBD_NUM);

	Common::KeyCode scummVMKeycode = ev.kbd.keycode;

	input.character = ev.kbd.ascii;
	input.type = SCI_EVENT_KEYBOARD;

	if (scummVMKeycode >= Common::KEYCODE_KP0 && scummVMKeycode <= Common::KEYCODE_KP9) {
		if (!(scummVMKeyFlags & Common::KBD_NUM)) {
			// HACK: Num-Lock not enabled
			// We shouldn't get a valid ascii code in these cases. We fix it here, so that cursor keys
			// on the numpad work properly.
			input.character = 0;
		}
	}

	if ((input.character) && (input.character <= 0xFF)) {
		// Directly accept most common keys without conversion
		if ((input.character >= 0x80) && (input.character <= 0xFF)) {
			// If there is no extended font, we will just clear the
			// current event.
			// Sierra SCI actually accepted those characters, but
			// didn't display them inside text edit controls because
			// the characters were missing inside the font(s).
			// We filter them out for non-multilingual games because
			// of that.
			if (!_fontIsExtended)
				return noEvent;
			// Convert 8859-1 characters to DOS (cp850/437) for
			// multilingual SCI01 games
			input.character = codePageMap88591ToDOS[input.character & 0x7f];
		}
		if (scummVMKeycode == Common::KEYCODE_TAB) {
			input.character = SCI_KEY_TAB;
			if (scummVMKeyFlags & Common::KBD_SHIFT)
				input.character = SCI_KEY_SHIFT_TAB;
		}
		if (scummVMKeycode == Common::KEYCODE_DELETE)
			input.character = SCI_KEY_DELETE;
	} else if ((scummVMKeycode >= Common::KEYCODE_F1) && scummVMKeycode <= Common::KEYCODE_F10) {
		// SCI_K_F1 == 59 << 8
		// SCI_K_SHIFT_F1 == 84 << 8
		if (!(scummVMKeyFlags & Common::KBD_SHIFT))
			input.character = SCI_KEY_F1 + ((scummVMKeycode - Common::KEYCODE_F1)<<8);
		else
			input.character = SCI_KEY_SHIFT_F1 + ((scummVMKeycode - Common::KEYCODE_F1)<<8);
	} else {
		// Special keys that need conversion
		for (int i = 0; i < ARRAYSIZE(keyMappings); i++) {
			if (keyMappings[i].scummVMKey == scummVMKeycode) {
				input.character = numlockOn ? keyMappings[i].sciKeyNumlockOn : keyMappings[i].sciKeyNumlockOff;
				break;
			}
		}
	}

	// When Ctrl AND Alt are pressed together with a regular key, Linux will give us control-key, Windows will give
	//  us the actual key. My opinion is that windows is right, because under DOS the keys worked the same, anyway
	//  we support the other case as well
	if ((scummVMKeyFlags & Common::KBD_ALT) && input.character > 0 && input.character < 27)
		input.character += 96; // 0x01 -> 'a'

	// Scancodify if appropriate
	if (scummVMKeyFlags & Common::KBD_ALT)
		input.character = altify(input.character);
	if (getSciVersion() <= SCI_VERSION_1_MIDDLE && (scummVMKeyFlags & Common::KBD_CTRL) && input.character > 0 && input.character < 27)
		input.character += 96; // 0x01 -> 'a'
#ifdef ENABLE_SCI32
	if (getSciVersion() >= SCI_VERSION_2 && (scummVMKeyFlags & Common::KBD_CTRL) && input.character == 'c') {
		input.character = SCI_KEY_ETX;
	}
#endif

	// If no actual key was pressed (e.g. if only a modifier key was pressed),
	// ignore the event
	if (!input.character)
		return noEvent;

	return input;
}