diff --git a/server/src/core/trainproperty.cpp b/server/src/core/trainproperty.cpp new file mode 100644 index 00000000..9cd01057 --- /dev/null +++ b/server/src/core/trainproperty.cpp @@ -0,0 +1,140 @@ +/** + * server/src/core/trainproperty.cpp + * + * This file is part of the traintastic source code. + * + * Copyright (C) 2019-2020 Reinder Feenstra + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "trainproperty.hpp" +#include "../train/train.hpp" + +using T = Train; + +TrainProperty::TrainProperty(Object* object, const std::string& name, const std::shared_ptr& value, PropertyFlags flags) : + AbstractObjectProperty(object, name, flags), + m_value{value} +{ +} + +TrainProperty::TrainProperty(Object* object, const std::string& name, nullptr_t, PropertyFlags flags) : + TrainProperty(object, name, std::shared_ptr(), flags) +{ +} + +TrainProperty::TrainProperty(Object* object, const std::string& name, const std::shared_ptr& value, PropertyFlags flags, OnSet onSet) : + TrainProperty(object, name, value, flags) +{ + m_onSet = onSet; +} + +TrainProperty::TrainProperty(Object* object, const std::string& name, nullptr_t, PropertyFlags flags, OnSet onSet) : + TrainProperty(object, name, std::shared_ptr(), flags, onSet) +{ +} + +const std::shared_ptr& TrainProperty::value() const +{ + return m_value; +} + +void TrainProperty::setValue(const std::shared_ptr& value) +{ + assert(isWriteable()); + if(m_value == value) + return; + else if(!isWriteable()) + throw not_writable_error(); + else if(!m_onSet || m_onSet(value)) + { + m_value = value; + changed(); + } + else + throw invalid_value_error(); + } + +void TrainProperty::setValueInternal(const std::shared_ptr& value) +{ + if(m_value != value) + { + m_value = value; + changed(); + } +} + +const T* TrainProperty::operator ->() const +{ + return m_value.get(); +} + +T* TrainProperty::operator ->() +{ + return m_value.get(); +} + +const T& TrainProperty::operator *() const +{ + return *m_value; +} + +T& TrainProperty::operator *() +{ + return *m_value; +} + +TrainProperty::operator bool() +{ + return m_value.operator bool(); +} + +TrainProperty& TrainProperty::operator =(const std::shared_ptr& value) +{ + setValue(value); + return *this; +} + +ObjectPtr TrainProperty::toObject() const +{ + return std::dynamic_pointer_cast(m_value); +} + +void TrainProperty::fromObject(const ObjectPtr& value) +{ + if(value) + { + if(std::shared_ptr v = std::dynamic_pointer_cast(value)) + setValue(v); + else + throw conversion_error(); + } + else + setValue(nullptr); +} + +void TrainProperty::load(const ObjectPtr& value) +{ + if(value) + { + if(std::shared_ptr v = std::dynamic_pointer_cast(value)) + m_value = v; + else + throw conversion_error(); + } + else + m_value.reset(); +} diff --git a/server/src/core/trainproperty.hpp b/server/src/core/trainproperty.hpp new file mode 100644 index 00000000..c117f2c6 --- /dev/null +++ b/server/src/core/trainproperty.hpp @@ -0,0 +1,68 @@ +/** + * server/src/core/trainproperty.hpp + * + * This file is part of the traintastic source code. + * + * Copyright (C) 2019-2020 Reinder Feenstra + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef TRAINTASTIC_SERVER_CORE_TRAINPROPERTY_HPP +#define TRAINTASTIC_SERVER_CORE_TRAINPROPERTY_HPP + +#include "abstractobjectproperty.hpp" +#include + +class Train; + +//! workaround for ObjectProperty +class TrainProperty : public AbstractObjectProperty +{ + public: + using OnSet = std::function& value)>; + + protected: + std::shared_ptr m_value; + OnSet m_onSet; + + public: + TrainProperty(Object* object, const std::string& name, const std::shared_ptr& value, PropertyFlags flags); + TrainProperty(Object* object, const std::string& name, nullptr_t, PropertyFlags flags); + TrainProperty(Object* object, const std::string& name, const std::shared_ptr& value, PropertyFlags flags, OnSet onSet); + TrainProperty(Object* object, const std::string& name, nullptr_t, PropertyFlags flags, OnSet onSet); + + const std::shared_ptr& value() const; + + void setValue(const std::shared_ptr& value); + void setValueInternal(const std::shared_ptr& value); + + const Train* operator ->() const; + Train* operator ->(); + + const Train& operator *() const; + Train& operator *(); + + operator bool(); + + TrainProperty& operator =(const std::shared_ptr& value); + + ObjectPtr toObject() const final; + void fromObject(const ObjectPtr& value) final; + + void load(const ObjectPtr& value) final; +}; + +#endif diff --git a/server/src/train/train.cpp b/server/src/train/train.cpp index aeaa18bf..bb6337dd 100644 --- a/server/src/train/train.cpp +++ b/server/src/train/train.cpp @@ -34,8 +34,11 @@ Train::Train(const std::weak_ptr& world, std::string_view _id) : speedMax{*this, "speed_max", 120, SpeedUnit::KiloMeterPerHour, PropertyFlags::ReadWrite | PropertyFlags::Store}, throttleSpeed{*this, "throttle_speed", 0, SpeedUnit::KiloMeterPerHour, PropertyFlags::ReadWrite | PropertyFlags::StoreState}, weight{*this, "weight", 0, WeightUnit::Ton, PropertyFlags::ReadOnly | PropertyFlags::Store}, + vehicles{this, "vehicles", nullptr, PropertyFlags::ReadOnly | PropertyFlags::Store | PropertyFlags::SubObject}, notes{this, "notes", "", PropertyFlags::ReadWrite | PropertyFlags::Store} { + vehicles.setValueInternal(std::make_shared(*this, vehicles.name())); + auto w = world.lock(); const bool editable = w && contains(w->state.value(), WorldState::Edit); @@ -43,12 +46,16 @@ Train::Train(const std::weak_ptr& world, std::string_view _id) : m_interfaceItems.add(name); m_interfaceItems.add(lob); Attributes::addValues(direction, DirectionValues); + Attributes::addObjectEditor(direction, false); m_interfaceItems.add(direction); + Attributes::addObjectEditor(speed, false); m_interfaceItems.add(speed); Attributes::addEnabled(speedMax, editable); m_interfaceItems.add(speedMax); + Attributes::addObjectEditor(throttleSpeed, false); m_interfaceItems.add(throttleSpeed); m_interfaceItems.add(weight); + m_interfaceItems.add(vehicles); m_interfaceItems.add(notes); } diff --git a/server/src/train/train.hpp b/server/src/train/train.hpp index 07689ab0..0863812f 100644 --- a/server/src/train/train.hpp +++ b/server/src/train/train.hpp @@ -28,6 +28,7 @@ #include "../core/speedproperty.hpp" #include "../core/weightproperty.hpp" #include "../enum/direction.hpp" +#include "../vehicle/rail/railvehiclelist.hpp" class Train : public IdObject { @@ -46,6 +47,7 @@ class Train : public IdObject SpeedProperty speedMax; SpeedProperty throttleSpeed; WeightProperty weight; + ObjectProperty vehicles; Property notes; Train(const std::weak_ptr& world, std::string_view _id); diff --git a/server/src/vehicle/rail/railvehicle.cpp b/server/src/vehicle/rail/railvehicle.cpp index a436ac94..8b2dc611 100644 --- a/server/src/vehicle/rail/railvehicle.cpp +++ b/server/src/vehicle/rail/railvehicle.cpp @@ -28,6 +28,7 @@ RailVehicle::RailVehicle(const std::weak_ptr& world, std::string_view _id) : Vehicle(world, _id), decoder{this, "decoder", nullptr, PropertyFlags::ReadWrite | PropertyFlags::Store}, + train{this, "train", nullptr, PropertyFlags::ReadOnly | PropertyFlags::Store}, lob{*this, "lob", 0, LengthUnit::MilliMeter, PropertyFlags::ReadWrite | PropertyFlags::Store}, speedMax{*this, "speed_max", 0, SpeedUnit::KiloMeterPerHour, PropertyFlags::ReadWrite | PropertyFlags::Store}, weight{*this, "weight", 0, WeightUnit::Ton, PropertyFlags::ReadWrite | PropertyFlags::Store, [this](double, WeightUnit){ updateTotalWeight(); }}, @@ -38,6 +39,7 @@ RailVehicle::RailVehicle(const std::weak_ptr& world, std::string_view _id Attributes::addEnabled(decoder, editable); m_interfaceItems.insertBefore(decoder, notes); + m_interfaceItems.insertBefore(train, notes); Attributes::addEnabled(lob, editable); m_interfaceItems.insertBefore(lob, notes); Attributes::addEnabled(speedMax, editable); diff --git a/server/src/vehicle/rail/railvehicle.hpp b/server/src/vehicle/rail/railvehicle.hpp index 9d694339..2a434717 100644 --- a/server/src/vehicle/rail/railvehicle.hpp +++ b/server/src/vehicle/rail/railvehicle.hpp @@ -24,6 +24,7 @@ #define TRAINTASTIC_SERVER_VEHICLE_RAIL_RAILVEHICLE_HPP #include "../vehicle.hpp" +#include "../../core/trainproperty.hpp" #include "../../core/lengthproperty.hpp" #include "../../core/speedproperty.hpp" #include "../../core/weightproperty.hpp" @@ -42,6 +43,7 @@ class RailVehicle : public Vehicle public: ObjectProperty decoder; + TrainProperty train; LengthProperty lob; SpeedProperty speedMax; WeightProperty weight;