diff --git a/src/common/engine/namedef.h b/src/common/engine/namedef.h index 3c67191cd..7f9024538 100644 --- a/src/common/engine/namedef.h +++ b/src/common/engine/namedef.h @@ -115,6 +115,8 @@ xx(State) xx(Fixed) xx(Vector2) xx(Vector3) +xx(FVector2) +xx(FVector3) xx(let) xx(Min) diff --git a/src/common/engine/serializer.h b/src/common/engine/serializer.h index b114923df..a16d348a4 100644 --- a/src/common/engine/serializer.h +++ b/src/common/engine/serializer.h @@ -326,6 +326,16 @@ inline FSerializer &Serialize(FSerializer &arc, const char *key, DVector2 &p, DV return arc.Array(key, &p[0], def? &(*def)[0] : nullptr, 2, true); } +inline FSerializer& Serialize(FSerializer& arc, const char* key, FVector3& p, FVector3* def) +{ + return arc.Array(key, &p[0], def ? &(*def)[0] : nullptr, 3, true); +} + +inline FSerializer& Serialize(FSerializer& arc, const char* key, FVector2& p, FVector2* def) +{ + return arc.Array(key, &p[0], def ? &(*def)[0] : nullptr, 2, true); +} + template inline FSerializer &Serialize(FSerializer &arc, const char *key, TAngle &p, TAngle *def) { diff --git a/src/common/scripting/backend/codegen.cpp b/src/common/scripting/backend/codegen.cpp index 0fd13f9ce..34f6d03b5 100644 --- a/src/common/scripting/backend/codegen.cpp +++ b/src/common/scripting/backend/codegen.cpp @@ -1688,6 +1688,13 @@ FxExpression *FxTypeCast::Resolve(FCompileContext &ctx) delete this; return x; } + else if ((basex->IsVector2() && IsVector2()) || (basex->IsVector3() && IsVector3())) + { + auto x = basex; + basex = nullptr; + delete this; + return x; + } // todo: pointers to class objects. // All other types are only compatible to themselves and have already been handled above by the equality check. // Anything that falls through here is not compatible and must print an error. @@ -2764,7 +2771,7 @@ FxExpression *FxAddSub::Resolve(FCompileContext& ctx) else if (left->IsVector() && right->IsVector()) { // a vector2 can be added to or subtracted from a vector 3 but it needs to be the right operand. - if (left->ValueType == right->ValueType || (left->ValueType == TypeVector3 && right->ValueType == TypeVector2)) + if (left->ValueType == right->ValueType || (left->IsVector3() && right->IsVector2())) { ValueType = left->ValueType; } @@ -2857,8 +2864,9 @@ ExpEmit FxAddSub::Emit(VMFunctionBuilder *build) if (IsVector()) { assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); - build->Emit(right->ValueType == TypeVector2? OP_ADDV2_RR : OP_ADDV3_RR, to.RegNum, op1.RegNum, op2.RegNum); - if (left->ValueType == TypeVector3 && right->ValueType == TypeVector2 && to.RegNum != op1.RegNum) + + build->Emit(right->IsVector2() ? OP_ADDV2_RR : OP_ADDV3_RR, to.RegNum, op1.RegNum, op2.RegNum); + if (left->IsVector3() && right->IsVector2() && to.RegNum != op1.RegNum) { // must move the z-coordinate build->Emit(OP_MOVEF, to.RegNum + 2, op1.RegNum + 2); @@ -2890,7 +2898,7 @@ ExpEmit FxAddSub::Emit(VMFunctionBuilder *build) if (IsVector()) { assert(op1.RegType == REGT_FLOAT && op2.RegType == REGT_FLOAT); - build->Emit(right->ValueType == TypeVector2 ? OP_SUBV2_RR : OP_SUBV3_RR, to.RegNum, op1.RegNum, op2.RegNum); + build->Emit(right->IsVector2() ? OP_SUBV2_RR : OP_SUBV3_RR, to.RegNum, op1.RegNum, op2.RegNum); return to; } else if (ValueType->GetRegType() == REGT_FLOAT) @@ -3093,11 +3101,11 @@ ExpEmit FxMulDiv::Emit(VMFunctionBuilder *build) int op; if (op2.Konst) { - op = Operator == '*' ? (ValueType == TypeVector2 ? OP_MULVF2_RK : OP_MULVF3_RK) : (ValueType == TypeVector2 ? OP_DIVVF2_RK : OP_DIVVF3_RK); + op = Operator == '*' ? (IsVector2() ? OP_MULVF2_RK : OP_MULVF3_RK) : (IsVector2() ? OP_DIVVF2_RK : OP_DIVVF3_RK); } else { - op = Operator == '*' ? (ValueType == TypeVector2 ? OP_MULVF2_RR : OP_MULVF3_RR) : (ValueType == TypeVector2 ? OP_DIVVF2_RR : OP_DIVVF3_RR); + op = Operator == '*' ? (IsVector2() ? OP_MULVF2_RR : OP_MULVF3_RR) : (IsVector2() ? OP_DIVVF2_RR : OP_DIVVF3_RR); } op1.Free(build); op2.Free(build); @@ -9067,13 +9075,13 @@ ExpEmit FxVectorBuiltin::Emit(VMFunctionBuilder *build) ExpEmit op = Self->Emit(build); if (Function == NAME_Length) { - build->Emit(Self->ValueType == TypeVector2 ? OP_LENV2 : OP_LENV3, to.RegNum, op.RegNum); + build->Emit(Self->ValueType == TypeVector2 || Self->ValueType == TypeFVector2 ? OP_LENV2 : OP_LENV3, to.RegNum, op.RegNum); } else { ExpEmit len(build, REGT_FLOAT); - build->Emit(Self->ValueType == TypeVector2 ? OP_LENV2 : OP_LENV3, len.RegNum, op.RegNum); - build->Emit(Self->ValueType == TypeVector2 ? OP_DIVVF2_RR : OP_DIVVF3_RR, to.RegNum, op.RegNum, len.RegNum); + build->Emit(Self->ValueType == TypeVector2 || Self->ValueType == TypeFVector2 ? OP_LENV2 : OP_LENV3, len.RegNum, op.RegNum); + build->Emit(Self->ValueType == TypeVector2 || Self->ValueType == TypeFVector2 ? OP_DIVVF2_RR : OP_DIVVF3_RR, to.RegNum, op.RegNum, len.RegNum); len.Free(build); } op.Free(build); @@ -10734,6 +10742,10 @@ ExpEmit FxClassPtrCast::Emit(VMFunctionBuilder *build) FxLocalVariableDeclaration::FxLocalVariableDeclaration(PType *type, FName name, FxExpression *initval, int varflags, const FScriptPosition &p) :FxExpression(EFX_LocalVariableDeclaration, p) { + // Local FVector isn't different from Vector + if (type == TypeFVector2) type = TypeVector2; + else if (type == TypeFVector3) type = TypeVector3; + ValueType = type; VarFlags = varflags; Name = name; diff --git a/src/common/scripting/backend/codegen.h b/src/common/scripting/backend/codegen.h index 43fb7f061..0bf71e5a5 100644 --- a/src/common/scripting/backend/codegen.h +++ b/src/common/scripting/backend/codegen.h @@ -336,7 +336,9 @@ public: bool IsFloat() const { return ValueType->isFloat(); } bool IsInteger() const { return ValueType->isNumeric() && ValueType->isIntCompatible(); } bool IsPointer() const { return ValueType->isPointer(); } - bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3; }; + bool IsVector() const { return ValueType == TypeVector2 || ValueType == TypeVector3 || ValueType == TypeFVector2 || ValueType == TypeFVector3; }; + bool IsVector2() const { return ValueType == TypeVector2 || ValueType == TypeFVector2; }; + bool IsVector3() const { return ValueType == TypeVector3 || ValueType == TypeFVector3; }; bool IsBoolCompat() const { return ValueType->isScalar(); } bool IsObject() const { return ValueType->isObjectPointer(); } bool IsArray() const { return ValueType->isArray() || (ValueType->isPointer() && ValueType->toPointer()->PointedType->isArray()); } diff --git a/src/common/scripting/core/types.cpp b/src/common/scripting/core/types.cpp index c98cc7435..33380d1e3 100644 --- a/src/common/scripting/core/types.cpp +++ b/src/common/scripting/core/types.cpp @@ -61,6 +61,8 @@ PPointer *TypeFont; PStateLabel *TypeStateLabel; PStruct *TypeVector2; PStruct *TypeVector3; +PStruct* TypeFVector2; +PStruct* TypeFVector3; PStruct *TypeColorStruct; PStruct *TypeStringStruct; PPointer *TypeNullPtr; @@ -347,6 +349,28 @@ void PType::StaticInit() TypeVector3->RegCount = 3; + TypeFVector2 = new PStruct(NAME_FVector2, nullptr); + TypeFVector2->AddField(NAME_X, TypeFloat32); + TypeFVector2->AddField(NAME_Y, TypeFloat32); + TypeTable.AddType(TypeFVector2, NAME_Struct); + TypeFVector2->loadOp = OP_LFV2; + TypeFVector2->storeOp = OP_SFV2; + TypeFVector2->moveOp = OP_MOVEV2; + TypeFVector2->RegType = REGT_FLOAT; + TypeFVector2->RegCount = 2; + + TypeFVector3 = new PStruct(NAME_FVector3, nullptr); + TypeFVector3->AddField(NAME_X, TypeFloat32); + TypeFVector3->AddField(NAME_Y, TypeFloat32); + TypeFVector3->AddField(NAME_Z, TypeFloat32); + // allow accessing xy as a vector2 + TypeFVector3->Symbols.AddSymbol(Create(NAME_XY, TypeFVector2, VARF_Transient, 0)); + TypeTable.AddType(TypeFVector3, NAME_Struct); + TypeFVector3->loadOp = OP_LFV3; + TypeFVector3->storeOp = OP_SFV3; + TypeFVector3->moveOp = OP_MOVEV3; + TypeFVector3->RegType = REGT_FLOAT; + TypeFVector3->RegCount = 3; Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_sByte, TypeSInt8)); Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Byte, TypeUInt8)); @@ -366,6 +390,8 @@ void PType::StaticInit() Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_State, TypeState)); Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Vector2, TypeVector2)); Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_Vector3, TypeVector3)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_FVector2, TypeFVector2)); + Namespaces.GlobalNamespace->Symbols.AddSymbol(Create(NAME_FVector3, TypeFVector3)); } @@ -2321,6 +2347,33 @@ PStruct *NewStruct(FName name, PTypeBase *outer, bool native) PPrototype::PPrototype(const TArray &rettypes, const TArray &argtypes) : ArgumentTypes(argtypes), ReturnTypes(rettypes) { + for (int i = 0; i < ArgumentTypes.Size(); ++i) + { + auto& type = ArgumentTypes[i]; + + if (type == TypeFVector2) + { + type = TypeVector2; + } + else if (type == TypeFVector3) + { + type = TypeVector3; + } + } + + for (int i = 0; i < ReturnTypes.Size(); ++i) + { + auto& type = ReturnTypes[i]; + + if (type == TypeFVector2) + { + type = TypeVector2; + } + else if (type == TypeFVector3) + { + type = TypeVector3; + } + } } //========================================================================== diff --git a/src/common/scripting/core/types.h b/src/common/scripting/core/types.h index ae423af9d..e8d07e91a 100644 --- a/src/common/scripting/core/types.h +++ b/src/common/scripting/core/types.h @@ -612,8 +612,10 @@ extern PSound *TypeSound; extern PColor *TypeColor; extern PTextureID *TypeTextureID; extern PSpriteID *TypeSpriteID; -extern PStruct *TypeVector2; -extern PStruct *TypeVector3; +extern PStruct* TypeVector2; +extern PStruct* TypeVector3; +extern PStruct* TypeFVector2; +extern PStruct* TypeFVector3; extern PStruct *TypeColorStruct; extern PStruct *TypeStringStruct; extern PStatePointer *TypeState; diff --git a/src/common/scripting/frontend/zcc_compile.cpp b/src/common/scripting/frontend/zcc_compile.cpp index 8fc0bbe24..9e3daeaef 100644 --- a/src/common/scripting/frontend/zcc_compile.cpp +++ b/src/common/scripting/frontend/zcc_compile.cpp @@ -2026,7 +2026,7 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool do { auto type = DetermineType(c->Type(), f, f->Name, t, false, false); - if (type->isContainer() && type != TypeVector2 && type != TypeVector3) + if (type->isContainer() && type != TypeVector2 && type != TypeVector3 && type != TypeFVector2 && type != TypeFVector3) { // structs and classes only get passed by pointer. type = NewPointer(type); @@ -2036,6 +2036,14 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool Error(f, "The return type of a function cannot be a dynamic array"); break; } + else if (type == TypeFVector2) + { + type = TypeVector2; + } + else if (type == TypeFVector3) + { + type = TypeVector3; + } // TBD: disallow certain types? For now, let everything pass that isn't an array. rets.Push(type); t = static_cast(t->SiblingNext); @@ -2222,16 +2230,16 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool else if (type->GetRegType() != REGT_NIL) { if (p->Flags & ZCC_Out) flags |= VARF_Out; - if (type == TypeVector2) + if (type == TypeVector2 || type == TypeFVector2) { elementcount = 2; } - else if (type == TypeVector3) + else if (type == TypeVector3 || type == TypeFVector3) { elementcount = 3; } } - if (type->GetRegType() == REGT_NIL && type != TypeVector2 && type != TypeVector3) + if (type->GetRegType() == REGT_NIL && type != TypeVector2 && type != TypeVector3 && type != TypeFVector2 && type != TypeFVector3) { Error(p, "Invalid type %s for function parameter", type->DescriptiveName()); } @@ -2268,13 +2276,13 @@ void ZCCCompiler::CompileFunction(ZCC_StructWork *c, ZCC_FuncDeclarator *f, bool if (x != nullptr) { // Vectors need special treatment because they use more than one entry in the Defaults and do not report as actual constants - if (type == TypeVector2 && x->ExprType == EFX_VectorValue && static_cast(x)->isConstVector(2)) + if ((type == TypeVector2 || type == TypeFVector2) && x->ExprType == EFX_VectorValue && static_cast(x)->isConstVector(2)) { auto vx = static_cast(x); vmval[0] = static_cast(vx->xyz[0])->GetValue().GetFloat(); vmval[1] = static_cast(vx->xyz[1])->GetValue().GetFloat(); } - else if (type == TypeVector3 && x->ExprType == EFX_VectorValue && static_cast(x)->isConstVector(3)) + else if ((type == TypeVector3 || type == TypeFVector3) && x->ExprType == EFX_VectorValue && static_cast(x)->isConstVector(3)) { auto vx = static_cast(x); vmval[0] = static_cast(vx->xyz[0])->GetValue().GetFloat(); diff --git a/src/common/scripting/jit/jit.cpp b/src/common/scripting/jit/jit.cpp index 9823a6029..8937fa1e0 100644 --- a/src/common/scripting/jit/jit.cpp +++ b/src/common/scripting/jit/jit.cpp @@ -304,12 +304,12 @@ void JitCompiler::SetupSimpleFrame() { cc.mov(regA[rega++], x86::ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, a))); } - else if (type == TypeVector2) + else if (type == TypeVector2 || type == TypeFVector2) { cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f))); cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f))); } - else if (type == TypeVector3) + else if (type == TypeVector3 || type == TypeFVector3) { cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f))); cc.movsd(regF[regf++], x86::qword_ptr(args, argsPos++ * sizeof(VMValue) + offsetof(VMValue, f))); diff --git a/src/common/scripting/jit/jit_load.cpp b/src/common/scripting/jit/jit_load.cpp index 0881cfd21..64231abf7 100644 --- a/src/common/scripting/jit/jit_load.cpp +++ b/src/common/scripting/jit/jit_load.cpp @@ -325,6 +325,54 @@ void JitCompiler::EmitLV3_R() cc.movsd(regF[A + 2], asmjit::x86::qword_ptr(tmp, 16)); } +void JitCompiler::EmitLFV2() +{ + EmitNullPointerThrow(B, X_READ_NIL); + auto tmp = newTempIntPtr(); + cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], konstd[C])); + cc.movss(regF[A], asmjit::x86::qword_ptr(tmp)); + cc.movss(regF[A + 1], asmjit::x86::qword_ptr(tmp, 4)); + cc.cvtss2sd(regF[A], regF[A]); + cc.cvtss2sd(regF[A + 1], regF[A + 1]); +} + +void JitCompiler::EmitLFV2_R() +{ + EmitNullPointerThrow(B, X_READ_NIL); + auto tmp = newTempIntPtr(); + cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], regD[C])); + cc.movss(regF[A], asmjit::x86::qword_ptr(tmp)); + cc.movss(regF[A + 1], asmjit::x86::qword_ptr(tmp, 8)); + cc.cvtss2sd(regF[A], regF[A]); + cc.cvtss2sd(regF[A + 1], regF[A + 1]); +} + +void JitCompiler::EmitLFV3() +{ + EmitNullPointerThrow(B, X_READ_NIL); + auto tmp = newTempIntPtr(); + cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], konstd[C])); + cc.movss(regF[A], asmjit::x86::qword_ptr(tmp)); + cc.movss(regF[A + 1], asmjit::x86::qword_ptr(tmp, 8)); + cc.movss(regF[A + 2], asmjit::x86::qword_ptr(tmp, 16)); + cc.cvtss2sd(regF[A], regF[A]); + cc.cvtss2sd(regF[A + 1], regF[A + 1]); + cc.cvtss2sd(regF[A + 2], regF[A + 2]); +} + +void JitCompiler::EmitLFV3_R() +{ + EmitNullPointerThrow(B, X_READ_NIL); + auto tmp = newTempIntPtr(); + cc.lea(tmp, asmjit::x86::qword_ptr(regA[B], regD[C])); + cc.movss(regF[A], asmjit::x86::qword_ptr(tmp)); + cc.movss(regF[A + 1], asmjit::x86::qword_ptr(tmp, 8)); + cc.movss(regF[A + 2], asmjit::x86::qword_ptr(tmp, 16)); + cc.cvtss2sd(regF[A], regF[A]); + cc.cvtss2sd(regF[A + 1], regF[A + 1]); + cc.cvtss2sd(regF[A + 2], regF[A + 2]); +} + static void SetString(FString *to, char **from) { *to = *from; diff --git a/src/common/scripting/jit/jit_store.cpp b/src/common/scripting/jit/jit_store.cpp index 6dc1a45a9..dc98374d1 100644 --- a/src/common/scripting/jit/jit_store.cpp +++ b/src/common/scripting/jit/jit_store.cpp @@ -161,6 +161,64 @@ void JitCompiler::EmitSV3_R() cc.movsd(asmjit::x86::qword_ptr(tmp, 16), regF[B + 2]); } +void JitCompiler::EmitSFV2() +{ + EmitNullPointerThrow(A, X_WRITE_NIL); + auto tmp = newTempIntPtr(); + cc.mov(tmp, regA[A]); + cc.add(tmp, konstd[C]); + + auto tmpF = newTempXmmSs(); + cc.cvtsd2ss(tmpF, regF[B]); + cc.movss(asmjit::x86::qword_ptr(tmp), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 1]); + cc.movss(asmjit::x86::qword_ptr(tmp, 4), tmpF); +} + +void JitCompiler::EmitSFV2_R() +{ + EmitNullPointerThrow(A, X_WRITE_NIL); + auto tmp = newTempIntPtr(); + cc.mov(tmp, regA[A]); + cc.add(tmp, regD[C]); + + auto tmpF = newTempXmmSs(); + cc.cvtsd2ss(tmpF, regF[B]); + cc.movss(asmjit::x86::qword_ptr(tmp), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 1]); + cc.movss(asmjit::x86::qword_ptr(tmp, 4), tmpF); +} + +void JitCompiler::EmitSFV3() +{ + EmitNullPointerThrow(A, X_WRITE_NIL); + auto tmp = newTempIntPtr(); + cc.mov(tmp, regA[A]); + cc.add(tmp, konstd[C]); + auto tmpF = newTempXmmSs(); + cc.cvtsd2ss(tmpF, regF[B]); + cc.movss(asmjit::x86::qword_ptr(tmp), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 1]); + cc.movss(asmjit::x86::qword_ptr(tmp, 4), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 2]); + cc.movss(asmjit::x86::qword_ptr(tmp, 4), tmpF); +} + +void JitCompiler::EmitSFV3_R() +{ + EmitNullPointerThrow(A, X_WRITE_NIL); + auto tmp = newTempIntPtr(); + cc.mov(tmp, regA[A]); + cc.add(tmp, regD[C]); + auto tmpF = newTempXmmSs(); + cc.cvtsd2ss(tmpF, regF[B]); + cc.movss(asmjit::x86::qword_ptr(tmp), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 1]); + cc.movss(asmjit::x86::qword_ptr(tmp, 4), tmpF); + cc.cvtsd2ss(tmpF, regF[B + 2]); + cc.movss(asmjit::x86::qword_ptr(tmp, 4), tmpF); +} + void JitCompiler::EmitSBIT() { EmitNullPointerThrow(A, X_WRITE_NIL); diff --git a/src/common/scripting/vm/vmexec.h b/src/common/scripting/vm/vmexec.h index a4d666dcc..fd3761171 100644 --- a/src/common/scripting/vm/vmexec.h +++ b/src/common/scripting/vm/vmexec.h @@ -263,39 +263,77 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) GETADDR(PB,RC,X_READ_NIL); reg.a[a] = *(void **)ptr; NEXTOP; - OP(LV2): + OP(LV2) : + ASSERTF(a + 1); ASSERTA(B); ASSERTKD(C); + GETADDR(PB, KC, X_READ_NIL); + { + auto v = (double*)ptr; + reg.f[a] = v[0]; + reg.f[a + 1] = v[1]; + } + NEXTOP; + OP(LV2_R) : + ASSERTF(a + 1); ASSERTA(B); ASSERTD(C); + GETADDR(PB, RC, X_READ_NIL); + { + auto v = (double*)ptr; + reg.f[a] = v[0]; + reg.f[a + 1] = v[1]; + } + NEXTOP; + OP(LV3) : + ASSERTF(a + 2); ASSERTA(B); ASSERTKD(C); + GETADDR(PB, KC, X_READ_NIL); + { + auto v = (double*)ptr; + reg.f[a] = v[0]; + reg.f[a + 1] = v[1]; + reg.f[a + 2] = v[2]; + } + NEXTOP; + OP(LV3_R) : + ASSERTF(a + 2); ASSERTA(B); ASSERTD(C); + GETADDR(PB, RC, X_READ_NIL); + { + auto v = (double*)ptr; + reg.f[a] = v[0]; + reg.f[a + 1] = v[1]; + reg.f[a + 2] = v[2]; + } + NEXTOP; + OP(LFV2): ASSERTF(a+1); ASSERTA(B); ASSERTKD(C); GETADDR(PB,KC,X_READ_NIL); { - auto v = (double *)ptr; + auto v = (float *)ptr; reg.f[a] = v[0]; reg.f[a+1] = v[1]; } NEXTOP; - OP(LV2_R): + OP(LFV2_R): ASSERTF(a+1); ASSERTA(B); ASSERTD(C); GETADDR(PB,RC,X_READ_NIL); { - auto v = (double *)ptr; + auto v = (float *)ptr; reg.f[a] = v[0]; reg.f[a+1] = v[1]; } NEXTOP; - OP(LV3): + OP(LFV3): ASSERTF(a+2); ASSERTA(B); ASSERTKD(C); GETADDR(PB,KC,X_READ_NIL); { - auto v = (double *)ptr; + auto v = (float *)ptr; reg.f[a] = v[0]; reg.f[a+1] = v[1]; reg.f[a+2] = v[2]; } NEXTOP; - OP(LV3_R): + OP(LFV3_R): ASSERTF(a+2); ASSERTA(B); ASSERTD(C); GETADDR(PB,RC,X_READ_NIL); { - auto v = (double *)ptr; + auto v = (float *)ptr; reg.f[a] = v[0]; reg.f[a+1] = v[1]; reg.f[a+2] = v[2]; @@ -430,6 +468,44 @@ static int ExecScriptFunc(VMFrameStack *stack, VMReturn *ret, int numret) v[2] = reg.f[B+2]; } NEXTOP; + OP(SFV2): + ASSERTA(a); ASSERTF(B+1); ASSERTKD(C); + GETADDR(PA,KC,X_WRITE_NIL); + { + auto v = (float *)ptr; + v[0] = reg.f[B]; + v[1] = reg.f[B+1]; + } + NEXTOP; + OP(SFV2_R): + ASSERTA(a); ASSERTF(B+1); ASSERTD(C); + GETADDR(PA,RC,X_WRITE_NIL); + { + auto v = (float *)ptr; + v[0] = reg.f[B]; + v[1] = reg.f[B+1]; + } + NEXTOP; + OP(SFV3): + ASSERTA(a); ASSERTF(B+2); ASSERTKD(C); + GETADDR(PA,KC,X_WRITE_NIL); + { + auto v = (float *)ptr; + v[0] = reg.f[B]; + v[1] = reg.f[B+1]; + v[2] = reg.f[B+2]; + } + NEXTOP; + OP(SFV3_R): + ASSERTA(a); ASSERTF(B+2); ASSERTD(C); + GETADDR(PA,RC,X_WRITE_NIL); + { + auto v = (float *)ptr; + v[0] = reg.f[B]; + v[1] = reg.f[B+1]; + v[2] = reg.f[B+2]; + } + NEXTOP; OP(SBIT): ASSERTA(a); ASSERTD(B); GETADDR(PA,0,X_WRITE_NIL); diff --git a/src/common/scripting/vm/vmops.h b/src/common/scripting/vm/vmops.h index 82b3cabc4..af7fb233b 100644 --- a/src/common/scripting/vm/vmops.h +++ b/src/common/scripting/vm/vmops.h @@ -53,6 +53,10 @@ xx(LV3, lv3, RVRPKI, LV3_R, 4, REGT_INT) // load vector3 xx(LV3_R, lv3, RVRPRI, NOP, 0, 0) xx(LCS, lcs, RSRPKI, LCS_R, 4, REGT_INT) // load string from char ptr. xx(LCS_R, lcs, RSRPRI, NOP, 0, 0) +xx(LFV2, lfv2, RVRPKI, LFV2_R, 4, REGT_INT) // load fvector2 +xx(LFV2_R, lfv2, RVRPRI, NOP, 0, 0) +xx(LFV3, lfv3, RVRPKI, LFV3_R, 4, REGT_INT) // load fvector3 +xx(LFV3_R, lfv3, RVRPRI, NOP, 0, 0) xx(LBIT, lbit, RIRPI8, NOP, 0, 0) // rA = !!(*rB & C) -- *rB is a byte @@ -77,6 +81,10 @@ xx(SV2, sv2, RPRVKI, SV2_R, 4, REGT_INT) // store vector2 xx(SV2_R, sv2, RPRVRI, NOP, 0, 0) xx(SV3, sv3, RPRVKI, SV3_R, 4, REGT_INT) // store vector3 xx(SV3_R, sv3, RPRVRI, NOP, 0, 0) +xx(SFV2, sfv2, RPRVKI, SFV2_R, 4, REGT_INT) // store fvector2 +xx(SFV2_R, sfv2, RPRVRI, NOP, 0, 0) +xx(SFV3, sfv3, RPRVKI, SFV3_R, 4, REGT_INT) // store fvector3 +xx(SFV3_R, sfv3, RPRVRI, NOP, 0, 0) xx(SBIT, sbit, RPRII8, NOP, 0, 0) // *rA |= C if rB is true, *rA &= ~C otherwise diff --git a/src/intermission/intermission.cpp b/src/intermission/intermission.cpp index 0db0cb0ef..30dc71231 100644 --- a/src/intermission/intermission.cpp +++ b/src/intermission/intermission.cpp @@ -670,7 +670,7 @@ void DIntermissionScreenCast::Drawer () // draw the current frame in the middle of the screen if (caststate != NULL) { - DVector2 castscale = mDefaults->Scale; + DVector2 castscale = DVector2(mDefaults->Scale.X, mDefaults->Scale.Y); int castsprite = caststate->sprite; diff --git a/src/playsim/actor.h b/src/playsim/actor.h index f075f0225..722f59b0c 100644 --- a/src/playsim/actor.h +++ b/src/playsim/actor.h @@ -1021,7 +1021,7 @@ public: DRotator Angles; DRotator ViewAngles; // Angle offsets for cameras TObjPtr ViewPos; // Position offsets for cameras - DVector2 Scale; // Scaling values; 1 is normal size + FVector2 Scale; // Scaling values; 1 is normal size double Alpha; // Since P_CheckSight makes an alpha check this can't be a float. It has to be a double. int sprite; // used to find patch_t and flip value diff --git a/src/playsim/p_user.cpp b/src/playsim/p_user.cpp index 3337a1d10..e6d0719f3 100644 --- a/src/playsim/p_user.cpp +++ b/src/playsim/p_user.cpp @@ -970,9 +970,9 @@ void P_CheckPlayerSprite(AActor *actor, int &spritenum, DVector2 &scale) if (player->userinfo.GetSkin() != 0 && !(actor->flags4 & MF4_NOSKIN)) { // Convert from default scale to skin scale. - DVector2 defscale = actor->GetDefault()->Scale; - scale.X *= Skins[player->userinfo.GetSkin()].Scale.X / defscale.X; - scale.Y *= Skins[player->userinfo.GetSkin()].Scale.Y / defscale.Y; + FVector2 defscale = actor->GetDefault()->Scale; + scale.X *= Skins[player->userinfo.GetSkin()].Scale.X / double(defscale.X); + scale.Y *= Skins[player->userinfo.GetSkin()].Scale.Y / double(defscale.Y); } // Set the crouch sprite? diff --git a/src/r_data/sprites.cpp b/src/r_data/sprites.cpp index b3b5cf451..f09bbe468 100644 --- a/src/r_data/sprites.cpp +++ b/src/r_data/sprites.cpp @@ -1000,7 +1000,7 @@ void R_InitSprites () auto type = GetDefaultByType(PlayerClasses[0].Type); Skins[i].range0start = type->IntVar(NAME_ColorRangeStart); Skins[i].range0end = type->IntVar(NAME_ColorRangeEnd); - Skins[i].Scale = type->Scale; + Skins[i].Scale = DVector2(type->Scale.X, type->Scale.Y); } R_InitSpriteDefs (); @@ -1019,7 +1019,7 @@ void R_InitSprites () Skins[i].Face = face == NAME_None? "STF" : face.GetChars(); Skins[i].range0start = basetype->IntVar(NAME_ColorRangeStart); Skins[i].range0end = basetype->IntVar(NAME_ColorRangeEnd); - Skins[i].Scale = basetype->Scale; + Skins[i].Scale = DVector2(basetype->Scale.X, basetype->Scale.Y); Skins[i].sprite = basetype->SpawnState->sprite; Skins[i].namespc = ns_global; diff --git a/src/rendering/hwrenderer/scene/hw_sprites.cpp b/src/rendering/hwrenderer/scene/hw_sprites.cpp index ede39e474..c60f472a6 100644 --- a/src/rendering/hwrenderer/scene/hw_sprites.cpp +++ b/src/rendering/hwrenderer/scene/hw_sprites.cpp @@ -719,7 +719,7 @@ void HWSprite::Process(HWDrawInfo *di, AActor* thing, sector_t * sector, area_t return; int spritenum = thing->sprite; - DVector2 sprscale = thing->Scale; + DVector2 sprscale(thing->Scale.X, thing->Scale.Y); if (thing->player != nullptr) { P_CheckPlayerSprite(thing, spritenum, sprscale); diff --git a/src/rendering/swrenderer/scene/r_opaque_pass.cpp b/src/rendering/swrenderer/scene/r_opaque_pass.cpp index 03e00b208..14c4703e3 100644 --- a/src/rendering/swrenderer/scene/r_opaque_pass.cpp +++ b/src/rendering/swrenderer/scene/r_opaque_pass.cpp @@ -1044,7 +1044,7 @@ namespace swrenderer sprite.spritenum = thing->sprite; sprite.tex = nullptr; sprite.voxel = nullptr; - sprite.spriteScale = thing->Scale; + sprite.spriteScale = DVector2(thing->Scale.X, thing->Scale.Y); sprite.renderflags = thing->renderflags; if (thing->player != nullptr) diff --git a/src/scripting/decorate/olddecorations.cpp b/src/scripting/decorate/olddecorations.cpp index 15722cd6f..914c05643 100644 --- a/src/scripting/decorate/olddecorations.cpp +++ b/src/scripting/decorate/olddecorations.cpp @@ -405,7 +405,7 @@ static void ParseInsideDecoration (Baggage &bag, AActor *defaults, else if (sc.Compare ("Scale")) { sc.MustGetFloat (); - defaults->Scale.X = defaults->Scale.Y = sc.Float; + defaults->Scale.X = defaults->Scale.Y = float(sc.Float); } else if (sc.Compare ("RenderStyle")) { diff --git a/src/scripting/thingdef_properties.cpp b/src/scripting/thingdef_properties.cpp index 48db073d0..061820ca7 100644 --- a/src/scripting/thingdef_properties.cpp +++ b/src/scripting/thingdef_properties.cpp @@ -618,7 +618,7 @@ DEFINE_PROPERTY(damage, X, Actor) DEFINE_PROPERTY(scale, F, Actor) { PROP_DOUBLE_PARM(id, 0); - defaults->Scale.X = defaults->Scale.Y = id; + defaults->Scale.X = defaults->Scale.Y = float(id); } //========================================================================== diff --git a/wadsrc/static/zscript/actors/actor.zs b/wadsrc/static/zscript/actors/actor.zs index 63f0a3f12..86e5e11b5 100644 --- a/wadsrc/static/zscript/actors/actor.zs +++ b/wadsrc/static/zscript/actors/actor.zs @@ -115,7 +115,7 @@ class Actor : Thinker native native double FloatSpeed; native SpriteID sprite; native uint8 frame; - native vector2 Scale; + native fvector2 Scale; native TextureID picnum; native double Alpha; native readonly color fillcolor; // must be set with SetShade to initialize correctly. @@ -374,8 +374,8 @@ class Actor : Thinker native native readonly deprecated("2.3", "Use Vel.X instead") double MomX; native readonly deprecated("2.3", "Use Vel.Y instead") double MomY; native readonly deprecated("2.3", "Use Vel.Z instead") double MomZ; - native deprecated("2.3", "Use Scale.X instead") double ScaleX; - native deprecated("2.3", "Use Scale.Y instead") double ScaleY; + native deprecated("2.3", "Use Scale.X instead") float ScaleX; + native deprecated("2.3", "Use Scale.Y instead") float ScaleY; //FStrifeDialogueNode *Conversation; // [RH] The dialogue to show when this actor is used.;