/* This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* MaSzyna EU07 locomotive simulator Copyright (C) 2001-2004 Marcin Wozniak */ #include "system.hpp" #include "classes.hpp" #pragma hdrstop #include "Timer.h" #include "QueryParserComp.hpp" #include "Model3d.h" #include "Gauge.h" #include "Console.h" TGauge::TGauge() { eType = gt_Unknown; fFriction = 0.0; fDesiredValue = 0.0; fValue = 0.0; fOffset = 0.0; fScale = 1.0; fStepSize = 5; // iChannel=-1; //kanał analogowej komunikacji zwrotnej SubModel = NULL; }; TGauge::~TGauge(){}; void TGauge::Clear() { SubModel = NULL; eType = gt_Unknown; fValue = 0; fDesiredValue = 0; }; void TGauge::Init(TSubModel *NewSubModel, TGaugeType eNewType, double fNewScale, double fNewOffset, double fNewFriction, double fNewValue) { // ustawienie parametrów animacji submodelu if (NewSubModel) { // warunek na wszelki wypadek, gdyby się submodel nie // podłączył fFriction = fNewFriction; fValue = fNewValue; fOffset = fNewOffset; fScale = fNewScale; SubModel = NewSubModel; eType = eNewType; if (eType == gt_Digital) { TSubModel *sm = SubModel->ChildGet(); do { // pętla po submodelach potomnych i obracanie ich o kąt zależy od // cyfry w (fValue) if (sm->pName) { // musi mieć niepustą nazwę if (sm->pName[0] >= '0') if (sm->pName[0] <= '9') sm->WillBeAnimated(); // wyłączenie optymalizacji } sm = sm->NextGet(); } while (sm); } else // a banan może być z optymalizacją? NewSubModel->WillBeAnimated(); // wyłączenie ignowania jedynkowego transformu } }; bool TGauge::Load(TQueryParserComp *Parser, TModel3d *md1, TModel3d *md2, double mul) { AnsiString str1 = Parser->GetNextSymbol(); AnsiString str2 = Parser->GetNextSymbol().LowerCase(); double val3 = Parser->GetNextSymbol().ToDouble() * mul; double val4 = Parser->GetNextSymbol().ToDouble(); double val5 = Parser->GetNextSymbol().ToDouble(); TSubModel *sm = md1->GetFromName(str1.c_str()); if (sm) // jeśli nie znaleziony md2 = NULL; // informacja, że znaleziony else if (md2) // a jest podany drugi model (np. zewnętrzny) sm = md2->GetFromName(str1.c_str()); // to może tam będzie, co za różnica gdzie if (str2 == "mov") Init(sm, gt_Move, val3, val4, val5); else if (str2 == "wip") Init(sm, gt_Wiper, val3, val4, val5); else if (str2 == "dgt") Init(sm, gt_Digital, val3, val4, val5); else Init(sm, gt_Rotate, val3, val4, val5); return (md2); // true, gdy podany model zewnętrzny, a w kabinie nie było }; void TGauge::PermIncValue(double fNewDesired) { fDesiredValue = fDesiredValue + fNewDesired * fScale + fOffset; if (fDesiredValue - fOffset > 360 / fScale) { fDesiredValue = fDesiredValue - (360 / fScale); fValue = fValue - (360 / fScale); } }; void TGauge::IncValue(double fNewDesired) { // używane tylko dla uniwersali fDesiredValue = fDesiredValue + fNewDesired * fScale + fOffset; if (fDesiredValue > fScale + fOffset) fDesiredValue = fScale + fOffset; }; void TGauge::DecValue(double fNewDesired) { // używane tylko dla uniwersali fDesiredValue = fDesiredValue - fNewDesired * fScale + fOffset; if (fDesiredValue < 0) fDesiredValue = 0; }; void TGauge::UpdateValue(double fNewDesired) { // ustawienie wartości docelowej fDesiredValue = fNewDesired * fScale + fOffset; }; void TGauge::PutValue(double fNewDesired) { // McZapkie-281102: natychmiastowe wpisanie wartosci fDesiredValue = fNewDesired * fScale + fOffset; fValue = fDesiredValue; }; void TGauge::Update() { float dt = Timer::GetDeltaTime(); if ((fFriction > 0) && (dt < 0.5 * fFriction)) // McZapkie-281102: // zabezpieczenie przed // oscylacjami dla dlugich // czasow fValue += dt * (fDesiredValue - fValue) / fFriction; else fValue = fDesiredValue; if (SubModel) { // warunek na wszelki wypadek, gdyby się submodel nie // podłączył TSubModel *sm; switch (eType) { case gt_Rotate: SubModel->SetRotate(float3(0, 1, 0), fValue * 360.0); break; case gt_Move: SubModel->SetTranslate(float3(0, 0, fValue)); break; case gt_Wiper: SubModel->SetRotate(float3(0, 1, 0), fValue * 360.0); sm = SubModel->ChildGet(); if (sm) { sm->SetRotate(float3(0, 1, 0), fValue * 360.0); sm = sm->ChildGet(); if (sm) sm->SetRotate(float3(0, 1, 0), fValue * 360.0); } break; case gt_Digital: // Ra 2014-07: licznik cyfrowy sm = SubModel->ChildGet(); AnsiString n = FormatFloat("0000000000", floor(fValue)); // na razie tak trochę bez sensu do { // pętla po submodelach potomnych i obracanie ich o kąt zależy od // cyfry w (fValue) if (sm->pName) { // musi mieć niepustą nazwę if (sm->pName[0] >= '0') if (sm->pName[0] <= '9') sm->SetRotate(float3(0, 1, 0), -36.0 * (n['0' + 10 - sm->pName[0]] - '0')); } sm = sm->NextGet(); } while (sm); break; } } }; void TGauge::Render(){}; void TGauge::AssignFloat(float *fValue) { cDataType = 'f'; fData = fValue; }; void TGauge::AssignDouble(double *dValue) { cDataType = 'd'; dData = dValue; }; void TGauge::AssignInt(int *iValue) { cDataType = 'i'; iData = iValue; }; void TGauge::UpdateValue() { // ustawienie wartości docelowej z parametru switch (cDataType) { // to nie jest zbyt optymalne, można by zrobić osobne funkcje case 'f': fDesiredValue = (*fData) * fScale + fOffset; break; case 'd': fDesiredValue = (*dData) * fScale + fOffset; break; case 'i': fDesiredValue = (*iData) * fScale + fOffset; break; } }; //--------------------------------------------------------------------------- #pragma package(smart_init)