diff --git a/src/common/engine/namedef.h b/src/common/engine/namedef.h index a67676c7a..9d5cb27ff 100644 --- a/src/common/engine/namedef.h +++ b/src/common/engine/namedef.h @@ -154,6 +154,8 @@ xx(Length) xx(LengthSquared) xx(Unit) xx(Angle) +xx(PlusZ) +xx(ToVector) xx(Size) xx(Push) xx(Insert) diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index bd597388d..6f6a8e025 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -8218,6 +8218,15 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) // Note: These builtins would better be relegated to the actual type objects, instead of polluting this file, but that's a task for later. // Texture builtins. + if (Self->ValueType->isNumeric()) + { + if (MethodName == NAME_ToVector) + { + Self = new FxToVector(Self); + SAFE_RESOLVE(Self, ctx); + return Self; + } + } else if (Self->ValueType == TypeTextureID) { if (MethodName == NAME_IsValid || MethodName == NAME_IsNull || MethodName == NAME_Exists || MethodName == NAME_SetInvalid || MethodName == NAME_SetNull) @@ -8263,7 +8272,7 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) else if (Self->IsVector()) { - // handle builtins: Vectors got 2: Length and Unit. + // handle builtins: Vectors got 5. if (MethodName == NAME_Length || MethodName == NAME_LengthSquared || MethodName == NAME_Unit || MethodName == NAME_Angle) { if (ArgList.Size() > 0) @@ -8277,6 +8286,20 @@ FxExpression *FxMemberFunctionCall::Resolve(FCompileContext& ctx) delete this; return x->Resolve(ctx); } + else if (MethodName == NAME_PlusZ && Self->IsVector3()) + { + if (ArgList.Size() != 1) + { + ScriptPosition.Message(MSG_ERROR, "Incorrect number of parameters in call to %s", MethodName.GetChars()); + delete this; + return nullptr; + } + auto x = new FxVectorPlusZ(Self, MethodName, ArgList[0]); + Self = nullptr; + ArgList[0] = nullptr; + delete this; + return x->Resolve(ctx); + } } else if (Self->ValueType == TypeString) @@ -9304,6 +9327,86 @@ ExpEmit FxVectorBuiltin::Emit(VMFunctionBuilder *build) return to; } +//========================================================================== +// +// FxPlusZ +// +//========================================================================== + + +FxVectorPlusZ::FxVectorPlusZ(FxExpression* self, FName name, FxExpression* z) + :FxExpression(EFX_VectorBuiltin, self->ScriptPosition), Function(name), Self(self), Z(new FxFloatCast(z)) +{ +} + +FxVectorPlusZ::~FxVectorPlusZ() +{ + SAFE_DELETE(Self); + SAFE_DELETE(Z); +} + +FxExpression* FxVectorPlusZ::Resolve(FCompileContext& ctx) +{ + SAFE_RESOLVE(Self, ctx); + SAFE_RESOLVE(Z, ctx); + assert(Self->IsVector3()); // should never be created for anything else. + ValueType = Self->ValueType; + return this; +} + +ExpEmit FxVectorPlusZ::Emit(VMFunctionBuilder* build) +{ + ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); + ExpEmit op = Self->Emit(build); + ExpEmit z = Z->Emit(build); + + build->Emit(OP_MOVEV2, to.RegNum, op.RegNum); + build->Emit(z.Konst ? OP_ADDF_RK : OP_ADDF_RR, to.RegNum + 2, op.RegNum + 2, z.RegNum); + + op.Free(build); + z.Free(build); + return to; +} + + +//========================================================================== +// +// FxPlusZ +// +//========================================================================== + + +FxToVector::FxToVector(FxExpression* self) + :FxExpression(EFX_ToVector, self->ScriptPosition), Self(new FxFloatCast(self)) +{ +} + +FxToVector::~FxToVector() +{ + SAFE_DELETE(Self); +} + +FxExpression* FxToVector::Resolve(FCompileContext& ctx) +{ + SAFE_RESOLVE(Self, ctx); + assert(Self->IsNumeric()); // should never be created for anything else. + ValueType = TypeVector2; + return this; +} + +ExpEmit FxToVector::Emit(VMFunctionBuilder* build) +{ + ExpEmit to(build, ValueType->GetRegType(), ValueType->GetRegCount()); + ExpEmit op = Self->Emit(build); + + build->Emit(OP_FLOP, to.RegNum, op.RegNum, FLOP_COS_DEG); + build->Emit(OP_FLOP, to.RegNum + 1, op.RegNum, FLOP_SIN_DEG); + + op.Free(build); + return to; +} + + //========================================================================== // // diff --git a/src/common/scripting/backend/codegen.h b/src/common/scripting/backend/codegen.h index ca8f0ce45..e2f167420 100644 --- a/src/common/scripting/backend/codegen.h +++ b/src/common/scripting/backend/codegen.h @@ -285,6 +285,7 @@ enum EFxType EFX_SwitchStatement, EFX_CaseStatement, EFX_VectorValue, + EFX_VectorPlusZ, EFX_VectorBuiltin, EFX_TypeCheck, EFX_DynamicCast, @@ -306,6 +307,7 @@ enum EFxType EFX_FontCast, EFX_LocalArrayDeclaration, EFX_OutVarDereference, + EFX_ToVector, EFX_COUNT }; @@ -1611,6 +1613,44 @@ public: ExpEmit Emit(VMFunctionBuilder *build); }; +//========================================================================== +// +// FxPlusZ +// +//========================================================================== + +class FxVectorPlusZ : public FxExpression +{ + FName Function; + FxExpression* Self; + FxExpression* Z; + +public: + + FxVectorPlusZ(FxExpression* self, FName name, FxExpression*); + ~FxVectorPlusZ(); + FxExpression* Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder* build); +}; + +//========================================================================== +// +// FxPlusZ +// +//========================================================================== + +class FxToVector : public FxExpression +{ + FxExpression* Self; + +public: + + FxToVector(FxExpression* self); + ~FxToVector(); + FxExpression* Resolve(FCompileContext&); + ExpEmit Emit(VMFunctionBuilder* build); +}; + //========================================================================== // // FxVectorBuiltin