mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-27 05:32:45 +00:00
MTROPOLIS: Annotate fields of STransCt (plug-in scene transition) modifier.
This commit is contained in:
parent
367afa4b53
commit
5e9f44d731
@ -22,6 +22,7 @@
|
||||
#include "mtropolis/miniscript.h"
|
||||
#include "common/config-manager.h"
|
||||
|
||||
#include "common/random.h"
|
||||
#include "common/memstream.h"
|
||||
|
||||
namespace MTropolis {
|
||||
@ -858,6 +859,245 @@ MiniscriptInstructionOutcome OrderedCompareInstruction::execute(MiniscriptThread
|
||||
BuiltinFunc::BuiltinFunc(BuiltinFunctionID bfid) : _funcID(bfid) {
|
||||
}
|
||||
|
||||
MiniscriptInstructionOutcome BuiltinFunc::execute(MiniscriptThread *thread) const {
|
||||
size_t stackArgsNeeded = 1;
|
||||
bool returnsValue = true;
|
||||
|
||||
if (thread->getStackSize() < stackArgsNeeded) {
|
||||
thread->error("Stack underflow");
|
||||
return kMiniscriptInstructionOutcomeFailed;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < stackArgsNeeded; i++) {
|
||||
MiniscriptInstructionOutcome outcome = thread->dereferenceRValue(i, false);
|
||||
if (outcome != kMiniscriptInstructionOutcomeContinue)
|
||||
return outcome;
|
||||
}
|
||||
|
||||
DynamicValue staticDest;
|
||||
DynamicValue *dest = nullptr;
|
||||
|
||||
if (returnsValue) {
|
||||
if (stackArgsNeeded > 0)
|
||||
dest = &thread->getStackValueFromTop(stackArgsNeeded - 1).value;
|
||||
else
|
||||
dest = &staticDest;
|
||||
}
|
||||
|
||||
MiniscriptInstructionOutcome outcome = executeFunction(thread, dest);
|
||||
if (outcome != kMiniscriptInstructionOutcomeContinue)
|
||||
return outcome;
|
||||
|
||||
if (stackArgsNeeded > 0) {
|
||||
size_t valuesToPop = stackArgsNeeded;
|
||||
if (returnsValue)
|
||||
valuesToPop--;
|
||||
|
||||
if (valuesToPop > 0)
|
||||
thread->popValues(valuesToPop);
|
||||
} else {
|
||||
if (returnsValue)
|
||||
thread->pushValue(staticDest);
|
||||
}
|
||||
|
||||
return kMiniscriptInstructionOutcomeContinue;
|
||||
}
|
||||
|
||||
MiniscriptInstructionOutcome BuiltinFunc::executeFunction(MiniscriptThread *thread, DynamicValue *returnValue) const {
|
||||
switch (_funcID) {
|
||||
case kSin:
|
||||
case kCos:
|
||||
case kRandom:
|
||||
case kSqrt:
|
||||
case kTan:
|
||||
case kAbs:
|
||||
case kSign:
|
||||
case kArctangent:
|
||||
case kExp:
|
||||
case kLn:
|
||||
case kLog:
|
||||
case kCosH:
|
||||
case kSinH:
|
||||
case kTanH:
|
||||
case kTrunc:
|
||||
case kRound:
|
||||
return executeSimpleNumericInstruction(thread, returnValue);
|
||||
case kRect2Polar:
|
||||
return executeRectToPolar(thread, returnValue);
|
||||
case kPolar2Rect:
|
||||
return executePolarToRect(thread, returnValue);
|
||||
case kNum2Str:
|
||||
return executeNum2Str(thread, returnValue);
|
||||
case kStr2Num:
|
||||
return executeStr2Num(thread, returnValue);
|
||||
default:
|
||||
thread->error("Unimplemented built-in function");
|
||||
return kMiniscriptInstructionOutcomeFailed;
|
||||
}
|
||||
}
|
||||
|
||||
MiniscriptInstructionOutcome BuiltinFunc::executeSimpleNumericInstruction(MiniscriptThread *thread, DynamicValue *returnValue) const {
|
||||
double result = 0.0;
|
||||
|
||||
double input = 0.0;
|
||||
const DynamicValue &inputDynamicValue = thread->getStackValueFromTop(0).value;
|
||||
|
||||
switch (inputDynamicValue.getType()) {
|
||||
case DynamicValueTypes::kInteger:
|
||||
input = inputDynamicValue.getInt();
|
||||
break;
|
||||
case DynamicValueTypes::kFloat:
|
||||
input = inputDynamicValue.getFloat();
|
||||
break;
|
||||
default:
|
||||
thread->error("Invalid numeric function input type");
|
||||
return kMiniscriptInstructionOutcomeFailed;
|
||||
}
|
||||
|
||||
switch (_funcID) {
|
||||
case kSin:
|
||||
result = sin(input * (M_PI / 180.0));
|
||||
break;
|
||||
case kCos:
|
||||
result = cos(input * (M_PI / 180.0));
|
||||
break;
|
||||
case kRandom:
|
||||
if (input < 1.5)
|
||||
result = 0.0;
|
||||
else {
|
||||
uint rngMax = static_cast<uint>(floor(input + 0.5)) - 1;
|
||||
result = thread->getRuntime()->getRandom()->getRandomNumber(rngMax);
|
||||
}
|
||||
break;
|
||||
case kSqrt:
|
||||
result = sqrt(input);
|
||||
break;
|
||||
case kTan:
|
||||
result = tan(input * (M_PI / 180.0));
|
||||
break;
|
||||
case kAbs:
|
||||
result = fabs(input);
|
||||
break;
|
||||
case kSign:
|
||||
if (input < 0.0)
|
||||
result = -1;
|
||||
else if (input > 0.0)
|
||||
result = 1;
|
||||
else
|
||||
result = 0;
|
||||
break;
|
||||
case kArctangent:
|
||||
result = atan(input) * (180.0 / M_PI);
|
||||
break;
|
||||
case kExp:
|
||||
result = exp(input);
|
||||
break;
|
||||
case kLn:
|
||||
result = log(input);
|
||||
break;
|
||||
case kLog:
|
||||
result = log10(input);
|
||||
break;
|
||||
case kCosH:
|
||||
result = cosh(input * (M_PI / 180.0));
|
||||
break;
|
||||
case kSinH:
|
||||
result = sinh(input * (M_PI / 180.0));
|
||||
break;
|
||||
case kTanH:
|
||||
result = tanh(input * (M_PI / 180.0));
|
||||
break;
|
||||
case kTrunc:
|
||||
result = trunc(input);
|
||||
break;
|
||||
case kRound:
|
||||
result = round(input);
|
||||
break;
|
||||
default:
|
||||
thread->error("Unimplemented numeric function");
|
||||
return kMiniscriptInstructionOutcomeFailed;
|
||||
}
|
||||
|
||||
returnValue->setFloat(result);
|
||||
|
||||
return kMiniscriptInstructionOutcomeContinue;
|
||||
}
|
||||
|
||||
MiniscriptInstructionOutcome BuiltinFunc::executeRectToPolar(MiniscriptThread *thread, DynamicValue *returnValue) const {
|
||||
const DynamicValue &inputDynamicValue = thread->getStackValueFromTop(0).value;
|
||||
|
||||
if (inputDynamicValue.getType() != DynamicValueTypes::kPoint) {
|
||||
thread->error("Polar to rect input must be a vector");
|
||||
return kMiniscriptInstructionOutcomeFailed;
|
||||
}
|
||||
|
||||
const Point16 &pt = inputDynamicValue.getPoint();
|
||||
|
||||
double angle = atan2(pt.x, pt.y);
|
||||
double magnitude = sqrt(pt.x * pt.x + pt.y * pt.y);
|
||||
|
||||
returnValue->setVector(AngleMagVector::create(angle, magnitude));
|
||||
|
||||
return kMiniscriptInstructionOutcomeContinue;
|
||||
}
|
||||
|
||||
MiniscriptInstructionOutcome BuiltinFunc::executePolarToRect(MiniscriptThread *thread, DynamicValue *returnValue) const {
|
||||
const DynamicValue &inputDynamicValue = thread->getStackValueFromTop(0).value;
|
||||
|
||||
if (inputDynamicValue.getType() != DynamicValueTypes::kVector) {
|
||||
thread->error("Polar to rect input must be a vector");
|
||||
return kMiniscriptInstructionOutcomeFailed;
|
||||
}
|
||||
|
||||
const AngleMagVector &vec = inputDynamicValue.getVector();
|
||||
|
||||
double x = cos(vec.angleRadians) * vec.magnitude;
|
||||
double y = sin(vec.angleRadians) * vec.magnitude;
|
||||
|
||||
returnValue->setPoint(Point16::create(static_cast<int16>(round(x)), static_cast<int16>(round(y))));
|
||||
|
||||
return kMiniscriptInstructionOutcomeContinue;
|
||||
}
|
||||
|
||||
MiniscriptInstructionOutcome BuiltinFunc::executeNum2Str(MiniscriptThread *thread, DynamicValue *returnValue) const {
|
||||
Common::String result;
|
||||
|
||||
const DynamicValue &inputDynamicValue = thread->getStackValueFromTop(0).value;
|
||||
switch (inputDynamicValue.getType()) {
|
||||
case DynamicValueTypes::kInteger:
|
||||
result.format("%i", static_cast<int>(inputDynamicValue.getInt()));
|
||||
break;
|
||||
case DynamicValueTypes::kFloat:
|
||||
result.format("%g", static_cast<double>(inputDynamicValue.getFloat()));
|
||||
break;
|
||||
default:
|
||||
thread->error("Invalid input value to num2str");
|
||||
return kMiniscriptInstructionOutcomeFailed;
|
||||
}
|
||||
|
||||
return kMiniscriptInstructionOutcomeContinue;
|
||||
}
|
||||
|
||||
MiniscriptInstructionOutcome BuiltinFunc::executeStr2Num(MiniscriptThread *thread, DynamicValue *returnValue) const {
|
||||
double result = 0.0;
|
||||
|
||||
const DynamicValue &inputDynamicValue = thread->getStackValueFromTop(0).value;
|
||||
if (inputDynamicValue.getType() != DynamicValueTypes::kString) {
|
||||
thread->error("Invalid input value to str2num");
|
||||
return kMiniscriptInstructionOutcomeFailed;
|
||||
}
|
||||
|
||||
const Common::String &str = inputDynamicValue.getString();
|
||||
if (str.size() == 0 || !sscanf(str.c_str(), "%lf", &result)) {
|
||||
thread->error("Couldn't parse number");
|
||||
return kMiniscriptInstructionOutcomeFailed;
|
||||
}
|
||||
|
||||
returnValue->setFloat(result);
|
||||
|
||||
return kMiniscriptInstructionOutcomeContinue;
|
||||
}
|
||||
|
||||
MiniscriptInstructionOutcome StrConcat::execute(MiniscriptThread *thread) const {
|
||||
if (thread->getStackSize() < 2) {
|
||||
thread->error("Stack underflow");
|
||||
|
@ -246,6 +246,15 @@ namespace MiniscriptInstructions {
|
||||
explicit BuiltinFunc(BuiltinFunctionID bfid);
|
||||
|
||||
private:
|
||||
MiniscriptInstructionOutcome execute(MiniscriptThread *thread) const override;
|
||||
|
||||
MiniscriptInstructionOutcome executeFunction(MiniscriptThread *thread, DynamicValue *returnValue) const;
|
||||
MiniscriptInstructionOutcome executeSimpleNumericInstruction(MiniscriptThread *thread, DynamicValue *returnValue) const;
|
||||
MiniscriptInstructionOutcome executeRectToPolar(MiniscriptThread *thread, DynamicValue *returnValue) const;
|
||||
MiniscriptInstructionOutcome executePolarToRect(MiniscriptThread *thread, DynamicValue *returnValue) const;
|
||||
MiniscriptInstructionOutcome executeNum2Str(MiniscriptThread *thread, DynamicValue *returnValue) const;
|
||||
MiniscriptInstructionOutcome executeStr2Num(MiniscriptThread *thread, DynamicValue *returnValue) const;
|
||||
|
||||
BuiltinFunctionID _funcID;
|
||||
};
|
||||
|
||||
|
@ -43,10 +43,9 @@ DataReadErrorCode STransCtModifier::load(PlugIn &plugIn, const PlugInModifier &p
|
||||
if (prefix.plugInRevision != 0)
|
||||
return kDataReadErrorUnsupportedRevision;
|
||||
|
||||
if (!reader.readU16(unknown1) || !unknown2.load(reader) || !reader.readU16(unknown3) || !unknown4.load(reader)
|
||||
|| !reader.readU16(unknown5) || !reader.readU32(unknown6) || !reader.readU16(unknown7) || !reader.readU32(unknown8)
|
||||
|| !reader.readU16(unknown9) || !reader.readU32(unknown10) || !reader.readU16(unknown11) || !reader.readU32(unknown12)
|
||||
|| !reader.readU16(unknown13) || !reader.readU32(unknown14) || !reader.readU16(unknown15) || !reader.readBytes(unknown16))
|
||||
if (!enableWhen.load(reader) || !disableWhen.load(reader) || !transitionType.load(reader) ||
|
||||
!transitionDirection.load(reader) || !unknown1.load(reader) || !steps.load(reader) ||
|
||||
!duration.load(reader) || !fullScreen.load(reader))
|
||||
return kDataReadErrorReadFailed;
|
||||
|
||||
return kDataReadErrorNone;
|
||||
|
@ -44,22 +44,14 @@ protected:
|
||||
};
|
||||
|
||||
struct STransCtModifier : public PlugInModifierData {
|
||||
uint16 unknown1; // Type tag? (0x17)
|
||||
Event unknown2; // Probably "apply when"
|
||||
uint16 unknown3; // Type tag? (0x17)
|
||||
Event unknown4; // Probably "remove when"
|
||||
uint16 unknown5; // Type tag? (1)
|
||||
uint32 unknown6;
|
||||
uint16 unknown7; // Type tag? (1)
|
||||
uint32 unknown8;
|
||||
uint16 unknown9; // Type tag? (1)
|
||||
uint32 unknown10;
|
||||
uint16 unknown11; // Type tag? (1)
|
||||
uint32 unknown12;
|
||||
uint16 unknown13; // Type tag? (1)
|
||||
uint32 unknown14;
|
||||
uint16 unknown15; // Type tag? (0x14)
|
||||
uint8 unknown16[2];
|
||||
PlugInTypeTaggedValue enableWhen; // Event
|
||||
PlugInTypeTaggedValue disableWhen; // Event
|
||||
PlugInTypeTaggedValue transitionType; // int
|
||||
PlugInTypeTaggedValue transitionDirection; // int
|
||||
PlugInTypeTaggedValue unknown1; // int, seems to always be 1
|
||||
PlugInTypeTaggedValue steps; // int, seems to always be 32
|
||||
PlugInTypeTaggedValue duration; // int, always observed as 60000
|
||||
PlugInTypeTaggedValue fullScreen; // bool
|
||||
|
||||
protected:
|
||||
DataReadErrorCode load(PlugIn &plugIn, const PlugInModifier &prefix, DataReader &reader) override;
|
||||
|
@ -30,6 +30,7 @@
|
||||
|
||||
#include "common/debug.h"
|
||||
#include "common/file.h"
|
||||
#include "common/random.h"
|
||||
#include "common/substream.h"
|
||||
#include "common/system.h"
|
||||
|
||||
@ -2483,6 +2484,8 @@ Runtime::SceneStackEntry::SceneStackEntry() {
|
||||
Runtime::Runtime(OSystem *system) : _nextRuntimeGUID(1), _realDisplayMode(kColorDepthModeInvalid), _fakeDisplayMode(kColorDepthModeInvalid),
|
||||
_displayWidth(1024), _displayHeight(768), _realTimeBase(0), _playTimeBase(0), _sceneTransitionState(kSceneTransitionStateNotTransitioning),
|
||||
_system(system), _lastFrameCursor(nullptr), _defaultCursor(new DefaultCursor()) {
|
||||
_random.reset(new Common::RandomSource("mtropolis"));
|
||||
|
||||
_vthread.reset(new VThread());
|
||||
|
||||
for (int i = 0; i < kColorDepthModeCount; i++) {
|
||||
@ -3187,7 +3190,9 @@ void Runtime::onMouseUp(int32 x, int32 y, Actions::MouseButton mButton) {
|
||||
_mouseFocusWindow.reset();
|
||||
}
|
||||
|
||||
|
||||
Common::RandomSource* Runtime::getRandom() const {
|
||||
return _random.get();
|
||||
}
|
||||
|
||||
void Runtime::ensureMainWindowExists() {
|
||||
// Maybe there's a better spot for this
|
||||
@ -4319,10 +4324,12 @@ bool VisualElement::readAttribute(MiniscriptThread *thread, DynamicValue &result
|
||||
if (attrib == "visible") {
|
||||
result.setBool(_visible);
|
||||
return true;
|
||||
}
|
||||
if (attrib == "direct") {
|
||||
} else if (attrib == "direct") {
|
||||
result.setBool(_directToScreen);
|
||||
return true;
|
||||
} else if (attrib == "position") {
|
||||
result.setPoint(Point16::create(_rect.left, _rect.top));
|
||||
return true;
|
||||
}
|
||||
|
||||
return Element::readAttribute(thread, result, attrib);
|
||||
@ -4332,10 +4339,12 @@ bool VisualElement::writeRefAttribute(MiniscriptThread *thread, DynamicValueWrit
|
||||
if (attrib == "visible") {
|
||||
DynamicValueWriteFuncHelper<VisualElement, &VisualElement::scriptSetVisibility>::create(this, writeProxy);
|
||||
return true;
|
||||
}
|
||||
if (attrib == "direct") {
|
||||
} else if (attrib == "direct") {
|
||||
DynamicValueWriteFuncHelper<VisualElement, &VisualElement::scriptSetDirect>::create(this, writeProxy);
|
||||
return true;
|
||||
} else if (attrib == "position") {
|
||||
DynamicValueWriteFuncHelper<VisualElement, &VisualElement::scriptSetPosition>::create(this, writeProxy);
|
||||
return true;
|
||||
}
|
||||
|
||||
return Element::writeRefAttribute(thread, writeProxy, attrib);
|
||||
@ -4374,6 +4383,34 @@ bool VisualElement::scriptSetDirect(const DynamicValue &dest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VisualElement::scriptSetPosition(const DynamicValue &dest) {
|
||||
if (dest.getType() == DynamicValueTypes::kPoint) {
|
||||
const Point16 &destPoint = dest.getPoint();
|
||||
int32 xDelta = destPoint.x - _rect.left;
|
||||
int32 yDelta = destPoint.y - _rect.right;
|
||||
|
||||
offsetTranslate(xDelta, yDelta);
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void VisualElement::offsetTranslate(int32 xDelta, int32 yDelta) {
|
||||
_rect.left += xDelta;
|
||||
_rect.right += xDelta;
|
||||
_rect.top += yDelta;
|
||||
_rect.bottom += yDelta;
|
||||
|
||||
for (const Common::SharedPtr<Structural> &child : _children) {
|
||||
if (child->isElement()) {
|
||||
Element *element = static_cast<Element *>(child.get());
|
||||
if (element->isVisual())
|
||||
static_cast<VisualElement *>(element)->offsetTranslate(xDelta, yDelta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VThreadState VisualElement::changeVisibilityTask(const ChangeFlagTaskData &taskData) {
|
||||
if (_visible != taskData.desiredFlag) {
|
||||
_visible = taskData.desiredFlag;
|
||||
|
@ -39,6 +39,12 @@
|
||||
|
||||
class OSystem;
|
||||
|
||||
namespace Common {
|
||||
|
||||
class RandomSource;
|
||||
|
||||
} // End of namespace Common
|
||||
|
||||
namespace Graphics {
|
||||
|
||||
struct WinCursorGroup;
|
||||
@ -398,6 +404,13 @@ struct AngleMagVector {
|
||||
return !((*this) == other);
|
||||
}
|
||||
|
||||
inline static AngleMagVector create(double angleRadians, double magnitude) {
|
||||
AngleMagVector result;
|
||||
result.angleRadians = angleRadians;
|
||||
result.magnitude = magnitude;
|
||||
return result;
|
||||
}
|
||||
|
||||
bool dynSetAngleDegrees(const DynamicValue &value);
|
||||
void dynGetAngleDegrees(DynamicValue &value) const;
|
||||
|
||||
@ -1267,6 +1280,8 @@ public:
|
||||
void onMouseMove(int32 x, int32 y);
|
||||
void onMouseUp(int32 x, int32 y, Actions::MouseButton mButton);
|
||||
|
||||
Common::RandomSource *getRandom() const;
|
||||
|
||||
#ifdef MTROPOLIS_DEBUG_ENABLE
|
||||
void debugSetEnabled(bool enabled);
|
||||
void debugBreak();
|
||||
@ -1360,6 +1375,8 @@ private:
|
||||
|
||||
Common::SharedPtr<Graphics::MacFontManager> _macFontMan;
|
||||
|
||||
Common::SharedPtr<Common::RandomSource> _random;
|
||||
|
||||
uint32 _nextRuntimeGUID;
|
||||
|
||||
bool _displayModeSupported[kColorDepthModeCount];
|
||||
@ -1823,6 +1840,9 @@ protected:
|
||||
bool loadCommon(const Common::String &name, uint32 guid, const Data::Rect &rect, uint32 elementFlags, uint16 layer, uint32 streamLocator, uint16 sectionID);
|
||||
|
||||
bool scriptSetDirect(const DynamicValue &dest);
|
||||
bool scriptSetPosition(const DynamicValue &dest);
|
||||
|
||||
void offsetTranslate(int32 xDelta, int32 yDelta);
|
||||
|
||||
struct ChangeFlagTaskData {
|
||||
bool desiredFlag;
|
||||
|
Loading…
x
Reference in New Issue
Block a user