diff options
Diffstat (limited to 'source')
28 files changed, 192 insertions, 79 deletions
diff --git a/source/base/StarCellularLightArray.cpp b/source/base/StarCellularLightArray.cpp index 60a6d95..99490ce 100644 --- a/source/base/StarCellularLightArray.cpp +++ b/source/base/StarCellularLightArray.cpp @@ -1,12 +1,13 @@ #include "StarCellularLightArray.hpp" +#include "StarInterpolation.hpp" // just specializing these in a cpp file so I can iterate on them without recompiling like 40 files!! namespace Star { template <> void CellularLightArray<ScalarLightTraits>::calculatePointLighting(size_t xmin, size_t ymin, size_t xmax, size_t ymax) { - float perBlockObstacleAttenuation = 1.0f / m_pointMaxObstacle; - float perBlockAirAttenuation = 1.0f / m_pointMaxAir; + float pointPerBlockObstacleAttenuation = 1.0f / m_pointMaxObstacle; + float pointPerBlockAirAttenuation = 1.0f / m_pointMaxAir; for (PointLight light : m_pointLights) { if (light.position[0] < 0 || light.position[0] > m_width - 1 || light.position[1] < 0 || light.position[1] > m_height - 1) @@ -14,8 +15,10 @@ void CellularLightArray<ScalarLightTraits>::calculatePointLighting(size_t xmin, float maxIntensity = ScalarLightTraits::maxIntensity(light.value); Vec2F beamDirection = Vec2F(1, 0).rotate(light.beamAngle); + float perBlockObstacleAttenuation = light.asSpread ? 1.0f / m_spreadMaxObstacle : pointPerBlockObstacleAttenuation; + float perBlockAirAttenuation = light.asSpread ? 1.0f / m_spreadMaxAir : pointPerBlockAirAttenuation; - float maxRange = maxIntensity * m_pointMaxAir; + float maxRange = maxIntensity * (light.asSpread ? m_spreadMaxAir : m_pointMaxAir); // The min / max considering the radius of the light size_t lxmin = std::floor(std::max<float>(xmin, light.position[0] - maxRange)); size_t lymin = std::floor(std::max<float>(ymin, light.position[1] - maxRange)); @@ -40,7 +43,7 @@ void CellularLightArray<ScalarLightTraits>::calculatePointLighting(size_t xmin, continue; Vec2F direction = relativeLightPosition / distance; - if (light.beam > 0.0f) { + if (light.beam > 0.0001f) { attenuation += (1.0f - light.beamAmbience) * clamp(light.beam * (1.0f - direction * beamDirection), 0.0f, 1.0f); if (attenuation >= 1.0f) continue; @@ -54,12 +57,21 @@ void CellularLightArray<ScalarLightTraits>::calculatePointLighting(size_t xmin, float circularizedPerBlockObstacleAttenuation = perBlockObstacleAttenuation / max(fabs(direction[0]), fabs(direction[1])); float blockAttenuation = lineAttenuation(blockPos, light.position, circularizedPerBlockObstacleAttenuation, remainingAttenuation); + attenuation += blockAttenuation; // Apply single obstacle boost (determine single obstacle by one // block unit of attenuation). - attenuation += blockAttenuation + min(blockAttenuation, circularizedPerBlockObstacleAttenuation) * m_pointObstacleBoost; - - if (attenuation < 1.0f) - setLight(x, y, lvalue + ScalarLightTraits::subtract(light.value, attenuation)); + if (!light.asSpread) + attenuation += min(blockAttenuation, circularizedPerBlockObstacleAttenuation) * m_pointObstacleBoost; + + if (attenuation < 1.0f) { + auto newLight = ScalarLightTraits::subtract(light.value, attenuation); + if (ScalarLightTraits::maxIntensity(newLight) > 0.0001f) { + if (light.asSpread) + setLight(x, y, lvalue + newLight * 0.25f); + else + setLight(x, y, lvalue + newLight); + } + } } } } @@ -67,8 +79,8 @@ void CellularLightArray<ScalarLightTraits>::calculatePointLighting(size_t xmin, template <> void CellularLightArray<ColoredLightTraits>::calculatePointLighting(size_t xmin, size_t ymin, size_t xmax, size_t ymax) { - float perBlockObstacleAttenuation = 1.0f / m_pointMaxObstacle; - float perBlockAirAttenuation = 1.0f / m_pointMaxAir; + float pointPerBlockObstacleAttenuation = 1.0f / m_pointMaxObstacle; + float pointPerBlockAirAttenuation = 1.0f / m_pointMaxAir; for (PointLight light : m_pointLights) { if (light.position[0] < 0 || light.position[0] > m_width - 1 || light.position[1] < 0 || light.position[1] > m_height - 1) @@ -76,8 +88,10 @@ void CellularLightArray<ColoredLightTraits>::calculatePointLighting(size_t xmin, float maxIntensity = ColoredLightTraits::maxIntensity(light.value); Vec2F beamDirection = Vec2F(1, 0).rotate(light.beamAngle); + float perBlockObstacleAttenuation = light.asSpread ? 1.0f / m_spreadMaxObstacle : pointPerBlockObstacleAttenuation; + float perBlockAirAttenuation = light.asSpread ? 1.0f / m_spreadMaxAir : pointPerBlockAirAttenuation; - float maxRange = maxIntensity * m_pointMaxAir; + float maxRange = maxIntensity * (light.asSpread ? m_spreadMaxAir : m_pointMaxAir); // The min / max considering the radius of the light size_t lxmin = std::floor(std::max<float>(xmin, light.position[0] - maxRange)); size_t lymin = std::floor(std::max<float>(ymin, light.position[1] - maxRange)); @@ -116,12 +130,21 @@ void CellularLightArray<ColoredLightTraits>::calculatePointLighting(size_t xmin, float circularizedPerBlockObstacleAttenuation = perBlockObstacleAttenuation / max(fabs(direction[0]), fabs(direction[1])); float blockAttenuation = lineAttenuation(blockPos, light.position, circularizedPerBlockObstacleAttenuation, remainingAttenuation); + attenuation += blockAttenuation; // Apply single obstacle boost (determine single obstacle by one // block unit of attenuation). - attenuation += blockAttenuation + min(blockAttenuation, circularizedPerBlockObstacleAttenuation) * m_pointObstacleBoost; - - if (attenuation < 1.0f) - setLight(x, y, lvalue + ColoredLightTraits::subtract(light.value, attenuation)); + if (!light.asSpread) + attenuation += min(blockAttenuation, circularizedPerBlockObstacleAttenuation) * m_pointObstacleBoost; + + if (attenuation < 1.0f) { + auto newLight = ColoredLightTraits::subtract(light.value, attenuation); + if (ColoredLightTraits::maxIntensity(newLight) > 0.0001f) { + if (light.asSpread) + setLight(x, y, lvalue + newLight * 0.25f); + else + setLight(x, y, lvalue + newLight); + } + } } } } diff --git a/source/base/StarCellularLightArray.hpp b/source/base/StarCellularLightArray.hpp index 225d42b..587ae1f 100644 --- a/source/base/StarCellularLightArray.hpp +++ b/source/base/StarCellularLightArray.hpp @@ -56,6 +56,7 @@ public: float beam; float beamAngle; float beamAmbience; + bool asSpread; }; void setParameters(unsigned spreadPasses, float spreadMaxAir, float spreadMaxObstacle, diff --git a/source/base/StarCellularLighting.cpp b/source/base/StarCellularLighting.cpp index 579f48a..3e5cf9a 100644 --- a/source/base/StarCellularLighting.cpp +++ b/source/base/StarCellularLighting.cpp @@ -109,12 +109,12 @@ void CellularLightingCalculator::addSpreadLight(Vec2F const& position, Vec3F con m_lightArray.left().addSpreadLight({arrayPosition, light}); } -void CellularLightingCalculator::addPointLight(Vec2F const& position, Vec3F const& light, float beam, float beamAngle, float beamAmbience) { +void CellularLightingCalculator::addPointLight(Vec2F const& position, Vec3F const& light, float beam, float beamAngle, float beamAmbience, bool asSpread) { Vec2F arrayPosition = position - Vec2F(m_calculationRegion.min()); if (m_monochrome) - m_lightArray.right().addPointLight({arrayPosition, light.max(), beam, beamAngle, beamAmbience}); + m_lightArray.right().addPointLight({arrayPosition, light.max(), beam, beamAngle, beamAmbience, asSpread}); else - m_lightArray.left().addPointLight({arrayPosition, light, beam, beamAngle, beamAmbience}); + m_lightArray.left().addPointLight({arrayPosition, light, beam, beamAngle, beamAmbience, asSpread}); } void CellularLightingCalculator::calculate(Image& output) { diff --git a/source/base/StarCellularLighting.hpp b/source/base/StarCellularLighting.hpp index 7cb230f..7c29bb8 100644 --- a/source/base/StarCellularLighting.hpp +++ b/source/base/StarCellularLighting.hpp @@ -136,7 +136,7 @@ public: void setCellIndex(size_t cellIndex, Vec3F const& light, bool obstacle); void addSpreadLight(Vec2F const& position, Vec3F const& light); - void addPointLight(Vec2F const& position, Vec3F const& light, float beam, float beamAngle, float beamAmbience); + void addPointLight(Vec2F const& position, Vec3F const& light, float beam, float beamAngle, float beamAmbience, bool asSpread = false); // Finish the calculation, and put the resulting color data in the given // output image. The image will be reset to the size of the region given in diff --git a/source/frontend/StarInventory.cpp b/source/frontend/StarInventory.cpp index 390558c..650d2e3 100644 --- a/source/frontend/StarInventory.cpp +++ b/source/frontend/StarInventory.cpp @@ -20,6 +20,8 @@ #include "StarJsonExtra.hpp" #include "StarStatistics.hpp" #include "StarAugmentItem.hpp" +#include "StarObjectItem.hpp" +#include "StarInteractionTypes.hpp" namespace Star { @@ -94,6 +96,27 @@ InventoryPane::InventoryPane(MainInterface* parent, PlayerPtr player, ContainerI rightClickCallback(slot); }; + auto middleClickCallback = [this](String const& bagType, Widget* widget) { + if (!m_player->inWorld()) + return; + + auto itemGrid = convert<ItemGridWidget>(widget); + InventorySlot inventorySlot = BagSlot(bagType, itemGrid->selectedIndex()); + auto inventory = m_player->inventory(); + if (auto sourceItem = as<ObjectItem>(itemGrid->selectedItem())) { + if (auto actionTypeName = sourceItem->instanceValue("interactAction")) { + auto actionType = InteractActionTypeNames.getLeft(actionTypeName.toString()); + if (actionType >= InteractActionType::OpenCraftingInterface && actionType <= InteractActionType::ScriptPane) { + auto actionData = sourceItem->instanceValue("interactData", Json()); + if (actionData.isType(Json::Type::Object)) + actionData = actionData.set("openWithInventory", false); + InteractAction action(actionType, m_player->entityId(), actionData); + m_player->interact(action); + } + } + } + }; + Json itemBagConfig = config.get("bagConfig"); auto bagOrder = itemBagConfig.toObject().keys().sorted([&itemBagConfig](String const& a, String const& b) { return itemBagConfig.get(a).getInt("order", 0) < itemBagConfig.get(b).getInt("order", 0); @@ -102,6 +125,7 @@ InventoryPane::InventoryPane(MainInterface* parent, PlayerPtr player, ContainerI auto itemGrid = itemBagConfig.get(name).getString("itemGrid"); invWindowReader.registerCallback(itemGrid, bind(leftClickCallback, name, _1)); invWindowReader.registerCallback(strf("{}.right", itemGrid), bind(bagGridCallback, name, _1)); + invWindowReader.registerCallback(strf("{}.middle", itemGrid), bind(middleClickCallback, name, _1)); } invWindowReader.registerCallback("close", [=](Widget*) { diff --git a/source/frontend/StarMainInterface.cpp b/source/frontend/StarMainInterface.cpp index 0d0cb5f..4098705 100644 --- a/source/frontend/StarMainInterface.cpp +++ b/source/frontend/StarMainInterface.cpp @@ -199,6 +199,9 @@ bool MainInterface::escapeDialogOpen() const { void MainInterface::openCraftingWindow(Json const& config, EntityId sourceEntityId) { if (m_craftingWindow && m_paneManager.isDisplayed(m_craftingWindow)) { m_paneManager.dismissPane(m_craftingWindow); + bool fromPlayer = false; + if (auto player = m_client->mainPlayer()) + fromPlayer = player->inWorld() && player->entityId() == sourceEntityId; if (m_craftingWindow->sourceEntityId() == sourceEntityId) { m_craftingWindow.reset(); return; @@ -215,21 +218,27 @@ void MainInterface::openCraftingWindow(Json const& config, EntityId sourceEntity void MainInterface::openMerchantWindow(Json const& config, EntityId sourceEntityId) { if (m_merchantWindow && m_paneManager.isDisplayed(m_merchantWindow)) { m_paneManager.dismissPane(m_merchantWindow); - if (m_merchantWindow->sourceEntityId() == sourceEntityId) { + bool fromPlayer = false; + if (auto player = m_client->mainPlayer()) + fromPlayer = player->inWorld() && player->entityId() == sourceEntityId; + if (!fromPlayer && m_merchantWindow->sourceEntityId() == sourceEntityId) { m_merchantWindow.reset(); return; } } + bool openWithInventory = config.getBool("openWithInventory", true); m_merchantWindow = make_shared<MerchantPane>(m_client->worldClient(), m_client->mainPlayer(), config, sourceEntityId); m_paneManager.displayPane(PaneLayer::Window, m_merchantWindow, - [this](PanePtr const&) { + [this, openWithInventory](PanePtr const&) { if (auto player = m_client->mainPlayer()) player->clearSwap(); - m_paneManager.dismissRegisteredPane(MainInterfacePanes::Inventory); + if (openWithInventory) + m_paneManager.dismissRegisteredPane(MainInterfacePanes::Inventory); }); - m_paneManager.displayRegisteredPane(MainInterfacePanes::Inventory); + if (openWithInventory) + m_paneManager.displayRegisteredPane(MainInterfacePanes::Inventory); m_paneManager.bringPaneAdjacent(m_paneManager.registeredPane(MainInterfacePanes::Inventory), m_merchantWindow, Root::singleton().assets()->json("/interface.config:bringAdjacentWindowGap").toFloat()); diff --git a/source/game/StarItemDrop.cpp b/source/game/StarItemDrop.cpp index f3a74c7..bc3d15f 100644 --- a/source/game/StarItemDrop.cpp +++ b/source/game/StarItemDrop.cpp @@ -320,7 +320,7 @@ void ItemDrop::render(RenderCallback* renderCallback) { void ItemDrop::renderLightSources(RenderCallback* renderCallback) { LightSource light; - light.pointLight = false; + light.type = LightType::Spread; light.color = Vec3F::filled(20.f / 255.f); light.position = position(); renderCallback->addLightSource(std::move(light)); diff --git a/source/game/StarLightSource.cpp b/source/game/StarLightSource.cpp index 65b7429..b20b15c 100644 --- a/source/game/StarLightSource.cpp +++ b/source/game/StarLightSource.cpp @@ -3,6 +3,12 @@ namespace Star { +EnumMap<LightType> const LightTypeNames{ + {LightType::Spread, "Spread"}, + {LightType::Point, "Point"}, + {LightType::PointAsSpread, "PointAsSpread"} +}; + void LightSource::translate(Vec2F const& pos) { position += pos; } @@ -10,7 +16,7 @@ void LightSource::translate(Vec2F const& pos) { DataStream& operator<<(DataStream& ds, LightSource const& lightSource) { ds.write(lightSource.position); ds.write(lightSource.color); - ds.write(lightSource.pointLight); + ds.write(lightSource.type); ds.write(lightSource.pointBeam); ds.write(lightSource.beamAngle); ds.write(lightSource.beamAmbience); @@ -21,7 +27,7 @@ DataStream& operator<<(DataStream& ds, LightSource const& lightSource) { DataStream& operator>>(DataStream& ds, LightSource& lightSource) { ds.read(lightSource.position); ds.read(lightSource.color); - ds.read(lightSource.pointLight); + ds.read(lightSource.type); ds.read(lightSource.pointBeam); ds.read(lightSource.beamAngle); ds.read(lightSource.beamAmbience); diff --git a/source/game/StarLightSource.hpp b/source/game/StarLightSource.hpp index a6948cb..673cd56 100644 --- a/source/game/StarLightSource.hpp +++ b/source/game/StarLightSource.hpp @@ -2,14 +2,22 @@ #include "StarVector.hpp" #include "StarDataStream.hpp" +#include "StarBiMap.hpp" namespace Star { +enum class LightType : uint8_t { + Spread = 0, + Point = 1, + PointAsSpread = 2 // Point with spread-like range +}; + +extern EnumMap<LightType> const LightTypeNames; + struct LightSource { Vec2F position; Vec3F color; - - bool pointLight; + LightType type; // pointBeam of 0.0 means light has no beam component, as pointBeam goes up, // the dropoff from the beamAngle becomes faster and faster. float pointBeam; diff --git a/source/game/StarMaterialDatabase.cpp b/source/game/StarMaterialDatabase.cpp index 6577937..6363c5d 100644 --- a/source/game/StarMaterialDatabase.cpp +++ b/source/game/StarMaterialDatabase.cpp @@ -379,7 +379,7 @@ CollisionKind MaterialDatabase::materialCollisionKind(MaterialId materialId) con } bool MaterialDatabase::canPlaceInLayer(MaterialId materialId, TileLayer layer) const { - return layer == TileLayer::Foreground || !getMaterialInfo(materialId)->foregroundOnly; + return layer != TileLayer::Background || !getMaterialInfo(materialId)->foregroundOnly; } ItemDescriptor MaterialDatabase::materialItemDrop(MaterialId materialId) const { diff --git a/source/game/StarNetworkedAnimator.cpp b/source/game/StarNetworkedAnimator.cpp index d013c48..ccec4fd 100644 --- a/source/game/StarNetworkedAnimator.cpp +++ b/source/game/StarNetworkedAnimator.cpp @@ -717,7 +717,7 @@ List<LightSource> NetworkedAnimator::lightSources(Vec2F const& translate) const lightSources.append(LightSource{ position + translate, color.toRgbF(), - pair.second.pointLight, + pair.second.pointLight ? LightType::Point : LightType::Spread, pair.second.pointBeam, pointAngle, pair.second.beamAmbience diff --git a/source/game/StarObject.cpp b/source/game/StarObject.cpp index 7bac350..dd19268 100644 --- a/source/game/StarObject.cpp +++ b/source/game/StarObject.cpp @@ -262,7 +262,7 @@ List<LightSource> Object::lightSources() const { LightSource lightSource; lightSource.position = position() + centerOfTile(orientation->lightPosition); lightSource.color = color.toRgbF(); - lightSource.pointLight = m_config->pointLight; + lightSource.type = m_config->lightType; lightSource.pointBeam = m_config->pointBeam; lightSource.beamAngle = orientation->beamAngle; lightSource.beamAmbience = m_config->beamAmbience; diff --git a/source/game/StarObjectDatabase.cpp b/source/game/StarObjectDatabase.cpp index 67a3c67..8ed56e4 100644 --- a/source/game/StarObjectDatabase.cpp +++ b/source/game/StarObjectDatabase.cpp @@ -495,7 +495,10 @@ ObjectConfigPtr ObjectDatabase::readConfig(String const& path) { objectConfig->lightColors[pair.first] = jsonToColor(pair.second); } - objectConfig->pointLight = config.getBool("pointLight", false); + if (auto lightType = config.optString("lightType")) + objectConfig->lightType = LightTypeNames.getLeft(*lightType); + else + objectConfig->lightType = (LightType)config.getBool("pointLight", false); objectConfig->pointBeam = config.getFloat("pointBeam", 0.0f); objectConfig->beamAmbience = config.getFloat("beamAmbience", 0.0f); diff --git a/source/game/StarObjectDatabase.hpp b/source/game/StarObjectDatabase.hpp index 76bae0f..ca44c2e 100644 --- a/source/game/StarObjectDatabase.hpp +++ b/source/game/StarObjectDatabase.hpp @@ -131,7 +131,7 @@ struct ObjectConfig { bool interactive; StringMap<Color> lightColors; - bool pointLight; + LightType lightType; float pointBeam; float beamAmbience; Maybe<PeriodicFunction<float>> lightFlickering; diff --git a/source/game/StarProjectile.cpp b/source/game/StarProjectile.cpp index 5a73e8b..d00b76b 100644 --- a/source/game/StarProjectile.cpp +++ b/source/game/StarProjectile.cpp @@ -379,7 +379,7 @@ void Projectile::renderLightSources(RenderCallback* renderCallback) { if (renderable.is<LightSource>()) renderCallback->addLightSource(renderable.get<LightSource>()); } - renderCallback->addLightSource({position(), m_config->lightColor.toRgbF(), m_config->pointLight, 0.0f, 0.0f, 0.0f}); + renderCallback->addLightSource({position(), m_config->lightColor.toRgbF(), m_config->lightType, 0.0f, 0.0f, 0.0f}); } Maybe<Json> Projectile::receiveMessage(ConnectionId sendingConnection, String const& message, JsonArray const& args) { @@ -825,7 +825,7 @@ void Projectile::processAction(Json const& action) { m_pendingRenderables.append(LightSource{ position(), jsonToColor(parameters.get("color")).toRgbF(), - parameters.getBool("pointLight", true), + (LightType)parameters.getBool("pointLight", true), 0.0f, 0.0f, 0.0f diff --git a/source/game/StarProjectileDatabase.cpp b/source/game/StarProjectileDatabase.cpp index dd7327b..c2a0c26 100644 --- a/source/game/StarProjectileDatabase.cpp +++ b/source/game/StarProjectileDatabase.cpp @@ -118,7 +118,10 @@ ProjectileConfigPtr ProjectileDatabase::readConfig(String const& path) { projectileConfig->lightColor = jsonToColor(config.get("lightColor", JsonArray{0, 0, 0})); projectileConfig->lightPosition = jsonToVec2F(config.get("lightPosition", JsonArray{0, 0})); - projectileConfig->pointLight = config.getBool("pointLight", false); + if (auto lightType = config.optString("lightType")) + projectileConfig->lightType = LightTypeNames.getLeft(*lightType); + else + projectileConfig->lightType = (LightType)config.getBool("pointLight", false); projectileConfig->persistentAudio = config.getString("persistentAudio", ""); diff --git a/source/game/StarProjectileDatabase.hpp b/source/game/StarProjectileDatabase.hpp index 833d0eb..d3cdd3d 100644 --- a/source/game/StarProjectileDatabase.hpp +++ b/source/game/StarProjectileDatabase.hpp @@ -68,7 +68,7 @@ struct ProjectileConfig { Color lightColor; Vec2F lightPosition; - bool pointLight = false; + LightType lightType = LightType::Spread; String persistentAudio; diff --git a/source/game/StarUniverseServer.cpp b/source/game/StarUniverseServer.cpp index 37bb8b7..af80e76 100644 --- a/source/game/StarUniverseServer.cpp +++ b/source/game/StarUniverseServer.cpp @@ -1650,14 +1650,14 @@ void UniverseServer::acceptConnection(UniverseConnection connection, Maybe<HostA WriteLocker clientsLocker(m_clientsLock); if (auto clashId = getClientForUuid(clientConnect->playerUuid)) { if (administrator) { - doDisconnection(*clashId, String("Duplicate Uuid joined and is Administrator so has priority.")); + doDisconnection(*clashId, "Duplicate Uuid joined and is Administrator so has priority."); } else { connectionFail("Duplicate player UUID"); return; } } - if (m_clients.size() + 1 > m_maxPlayers) { + if (m_clients.size() + 1 > m_maxPlayers && !administrator) { connectionFail("Max player connections"); return; } @@ -1734,8 +1734,14 @@ void UniverseServer::acceptConnection(UniverseConnection connection, Maybe<HostA clientWarpPlayer(clientId, WarpAlias::OwnShip); } } else { - Logger::info("UniverseServer: Spawning player at ship"); - clientWarpPlayer(clientId, WarpAlias::OwnShip); + Maybe<String> defaultReviveWarp = assets->json("/universe_server.config").optString("defaultReviveWarp"); + if (defaultReviveWarp) { + Logger::info("UniverseServer: Spawning player at default warp"); + clientWarpPlayer(clientId, parseWarpAction(*defaultReviveWarp)); + } else { + Logger::info("UniverseServer: Spawning player at ship"); + clientWarpPlayer(clientId, WarpAlias::OwnShip); + } } clientFlyShip(clientId, clientContext->shipCoordinate().location(), clientContext->shipLocation()); diff --git a/source/game/StarWorldClient.cpp b/source/game/StarWorldClient.cpp index df69b94..535980b 100644 --- a/source/game/StarWorldClient.cpp +++ b/source/game/StarWorldClient.cpp @@ -1652,10 +1652,15 @@ void WorldClient::lightingCalc() { for (auto const& light : lights) { Vec2F position = m_geometry.nearestTo(Vec2F(m_lightingCalculator.calculationRegion().min()), light.position); - if (light.pointLight) - m_lightingCalculator.addPointLight(position, light.color, light.pointBeam, light.beamAngle, light.beamAmbience); - else { + if (light.type == LightType::Spread) m_lightingCalculator.addSpreadLight(position, light.color); + else { + if (light.type == LightType::PointAsSpread) { + // hybrid (used for auto-converted object lights) - 75% spread, 25% point (2nd is applied elsewhere) + m_lightingCalculator.addSpreadLight(position, light.color * 0.75f); + m_lightingCalculator.addPointLight(position, light.color, light.pointBeam, light.beamAngle, light.beamAmbience, true); + } else // fully additive point light + m_lightingCalculator.addPointLight(position, light.color, light.pointBeam, light.beamAngle, light.beamAmbience); } } diff --git a/source/game/StarWorldImpl.hpp b/source/game/StarWorldImpl.hpp index dec827f..3e3728b 100644 --- a/source/game/StarWorldImpl.hpp +++ b/source/game/StarWorldImpl.hpp @@ -445,10 +445,10 @@ namespace WorldImpl { for (auto const& entity : entityMap->entityQuery(RectF(lighting.calculationRegion()))) { for (auto const& light : entity->lightSources()) { Vec2F position = worldGeometry.nearestTo(Vec2F(lighting.calculationRegion().min()), light.position); - if (light.pointLight) - lighting.addPointLight(position, light.color.sum() / 3.0f, light.pointBeam, light.beamAngle, light.beamAmbience); - else + if (light.type == LightType::Spread) lighting.addSpreadLight(position, light.color.sum() / 3.0f); + else + lighting.addPointLight(position, light.color.sum() / 3.0f, light.pointBeam, light.beamAngle, light.beamAmbience); } } diff --git a/source/game/items/StarInspectionTool.cpp b/source/game/items/StarInspectionTool.cpp index a9e3109..cdfe6c2 100644 --- a/source/game/items/StarInspectionTool.cpp +++ b/source/game/items/StarInspectionTool.cpp @@ -54,7 +54,7 @@ List<LightSource> InspectionTool::lightSources() const { float angle = world()->geometry().diff(owner()->aimPosition(), owner()->position()).angle(); LightSource lightSource; - lightSource.pointLight = true; + lightSource.type = LightType::Point; lightSource.position = owner()->position() + owner()->handPosition(hand(), m_lightPosition - m_handPosition); lightSource.color = m_lightColor.toRgbF(); lightSource.pointBeam = m_beamWidth; diff --git a/source/game/items/StarTools.cpp b/source/game/items/StarTools.cpp index 0f2781a..cde44b8 100644 --- a/source/game/items/StarTools.cpp +++ b/source/game/items/StarTools.cpp @@ -239,7 +239,7 @@ List<LightSource> Flashlight::lightSources() const { float angle = world()->geometry().diff(owner()->aimPosition(), owner()->position()).angle(); LightSource lightSource; - lightSource.pointLight = true; + lightSource.type = LightType::Point; lightSource.position = owner()->position() + owner()->handPosition(hand(), (m_lightPosition - m_handPosition) / TilePixels); lightSource.color = m_lightColor.toRgbF(); lightSource.pointBeam = m_beamWidth; diff --git a/source/game/scripting/StarLuaAnimationComponent.hpp b/source/game/scripting/StarLuaAnimationComponent.hpp index 8866724..799c76e 100644 --- a/source/game/scripting/StarLuaAnimationComponent.hpp +++ b/source/game/scripting/StarLuaAnimationComponent.hpp @@ -77,7 +77,7 @@ LuaAnimationComponent<Base>::LuaAnimationComponent() { m_lightSources.append({ lightSourceTable.get<Vec2F>("position"), lightSourceTable.get<Color>("color").toRgbF(), - lightSourceTable.get<Maybe<bool>>("pointLight").value(), + (LightType)lightSourceTable.get<Maybe<bool>>("pointLight").value(), lightSourceTable.get<Maybe<float>>("pointBeam").value(), lightSourceTable.get<Maybe<float>>("beamAngle").value(), lightSourceTable.get<Maybe<float>>("beamAmbience").value() diff --git a/source/windowing/StarItemGridWidget.cpp b/source/windowing/StarItemGridWidget.cpp index 3302ca6..be1cc42 100644 --- a/source/windowing/StarItemGridWidget.cpp +++ b/source/windowing/StarItemGridWidget.cpp @@ -106,7 +106,9 @@ Vec2I ItemGridWidget::positionOfSlot(size_t slotNumber) { bool ItemGridWidget::sendEvent(InputEvent const& event) { if (m_visible) { if (auto mouseButton = event.ptr<MouseButtonDownEvent>()) { - if (mouseButton->mouseButton == MouseButton::Left || (m_rightClickCallback && mouseButton->mouseButton == MouseButton::Right)) { + if (mouseButton->mouseButton == MouseButton::Left + || (m_rightClickCallback && mouseButton->mouseButton == MouseButton::Right) + || (m_middleClickCallback && mouseButton->mouseButton == MouseButton::Middle)) { Vec2I mousePos = *context()->mousePosition(event); for (size_t i = 0; i < (m_bag->size() - m_bagOffset) && i < unsigned(m_dimensions[0] * m_dimensions[1]); ++i) { Vec2I loc = locOfItemSlot(i); @@ -116,6 +118,8 @@ bool ItemGridWidget::sendEvent(InputEvent const& event) { m_selectedIndex = i; if (mouseButton->mouseButton == MouseButton::Right) m_rightClickCallback(this); + else if (mouseButton->mouseButton == MouseButton::Middle) + m_middleClickCallback(this); else m_callback(this); return true; @@ -145,6 +149,10 @@ void ItemGridWidget::setRightClickCallback(WidgetCallbackFunc callback) { m_rightClickCallback = callback; } +void ItemGridWidget::setMiddleClickCallback(WidgetCallbackFunc callback) { + m_middleClickCallback = callback; +} + void ItemGridWidget::setItemBag(ItemBagConstPtr bag) { m_bag = bag; diff --git a/source/windowing/StarItemGridWidget.hpp b/source/windowing/StarItemGridWidget.hpp index 79c0469..11a78b3 100644 --- a/source/windowing/StarItemGridWidget.hpp +++ b/source/windowing/StarItemGridWidget.hpp @@ -41,6 +41,7 @@ public: bool sendEvent(InputEvent const& event) override; void setCallback(WidgetCallbackFunc callback); void setRightClickCallback(WidgetCallbackFunc callback); + void setMiddleClickCallback(WidgetCallbackFunc callback); void setItemBag(ItemBagConstPtr bag); void setProgress(float progress); @@ -93,6 +94,7 @@ private: unsigned m_selectedIndex; WidgetCallbackFunc m_callback; WidgetCallbackFunc m_rightClickCallback; + WidgetCallbackFunc m_middleClickCallback; }; } diff --git a/source/windowing/StarItemSlotWidget.cpp b/source/windowing/StarItemSlotWidget.cpp index 2958957..93d95d3 100644 --- a/source/windowing/StarItemSlotWidget.cpp +++ b/source/windowing/StarItemSlotWidget.cpp @@ -67,12 +67,16 @@ void ItemSlotWidget::update(float dt) { bool ItemSlotWidget::sendEvent(InputEvent const& event) { if (m_visible) { if (auto mouseButton = event.ptr<MouseButtonDownEvent>()) { - if (mouseButton->mouseButton == MouseButton::Left || (m_rightClickCallback && mouseButton->mouseButton == MouseButton::Right)) { + if (mouseButton->mouseButton == MouseButton::Left + || (m_rightClickCallback && mouseButton->mouseButton == MouseButton::Right) + || (m_middleClickCallback && mouseButton->mouseButton == MouseButton::Middle)) { Vec2I mousePos = *context()->mousePosition(event); RectI itemArea = m_itemDraggableArea.translated(screenPosition()); if (itemArea.contains(mousePos)) { if (mouseButton->mouseButton == MouseButton::Right) m_rightClickCallback(this); + else if (mouseButton->mouseButton == MouseButton::Middle) + m_middleClickCallback(this); else m_callback(this); return true; @@ -92,6 +96,10 @@ void ItemSlotWidget::setRightClickCallback(WidgetCallbackFunc callback) { m_rightClickCallback = callback; } +void ItemSlotWidget::setMiddleClickCallback(WidgetCallbackFunc callback) { + m_middleClickCallback = callback; +} + void ItemSlotWidget::setItem(ItemPtr const& item) { m_item = item; } diff --git a/source/windowing/StarItemSlotWidget.hpp b/source/windowing/StarItemSlotWidget.hpp index 9e8772d..aaa4c9c 100644 --- a/source/windowing/StarItemSlotWidget.hpp +++ b/source/windowing/StarItemSlotWidget.hpp @@ -19,6 +19,7 @@ public: bool sendEvent(InputEvent const& event) override; void setCallback(WidgetCallbackFunc callback); void setRightClickCallback(WidgetCallbackFunc callback); + void setMiddleClickCallback(WidgetCallbackFunc callback); void setItem(ItemPtr const& item); ItemPtr item() const; void setProgress(float progress); @@ -61,6 +62,7 @@ private: WidgetCallbackFunc m_callback; WidgetCallbackFunc m_rightClickCallback; + WidgetCallbackFunc m_middleClickCallback; float m_progress; ProgressWidgetPtr m_durabilityBar; diff --git a/source/windowing/StarWidgetParsing.cpp b/source/windowing/StarWidgetParsing.cpp index b45294b..7a9ea4a 100644 --- a/source/windowing/StarWidgetParsing.cpp +++ b/source/windowing/StarWidgetParsing.cpp @@ -471,23 +471,27 @@ WidgetConstructResult WidgetParser::itemSlotHandler(String const& name, Json con String backingImage = config.getString("backingImage", ""); String callback = config.getString("callback", name); - String rightClickCallback; - if (callback.equals("null")) - rightClickCallback = callback; - else - rightClickCallback = callback + ".right"; + String rightClickCallback = callback.equals("null") ? callback : callback + ".right"; rightClickCallback = config.getString("rightClickCallback", rightClickCallback); + String middleClickCallback = callback.equals("null") ? callback : callback + ".middle"; + middleClickCallback = config.getString("middleClickCallback", middleClickCallback); + auto itemSlot = make_shared<ItemSlotWidget>(ItemPtr(), backingImage); - if (!m_callbacks.contains(callback)) - throw WidgetParserException::format("Failed to find itemSlot callback named: '{}'", callback); - itemSlot->setCallback(m_callbacks.get(callback)); + if (auto leftClickCallback = m_callbacks.ptr(callback)) + itemSlot->setCallback(*leftClickCallback); + else + throw WidgetParserException::format("Failed to find ItemSlot callback named: '{}'", callback); - if (!m_callbacks.contains(rightClickCallback)) - throw WidgetParserException::format("Failed to find itemslot rightClickCallback named: '{}'", rightClickCallback); + if (auto callback = m_callbacks.ptr(rightClickCallback)) + itemSlot->setRightClickCallback(*callback); + else + throw WidgetParserException::format("Failed to find ItemSlot rightClickCallback named: '{}'", rightClickCallback); + + if (auto callback = m_callbacks.ptr(middleClickCallback)) + itemSlot->setMiddleClickCallback(*callback); - itemSlot->setRightClickCallback(m_callbacks.get(rightClickCallback)); itemSlot->setBackingImageAffinity(config.getBool("showBackingImageWhenFull", false), config.getBool("showBackingImageWhenEmpty", true)); itemSlot->showDurability(config.getBool("showDurability", false)); itemSlot->showCount(config.getBool("showCount", true)); @@ -515,33 +519,34 @@ WidgetConstructResult WidgetParser::itemGridHandler(String const& name, Json con } catch (MapException const& e) { throw WidgetParserException::format("Malformed gui json, missing a required value in the map. {}", outputException(e, false)); } - - String backingImage = config.getString("backingImage", ""); + String callback = config.getString("callback", name); - String rightClickCallback; - if (callback.equals("null")) - rightClickCallback = callback; - else - rightClickCallback = callback + ".right"; + String rightClickCallback = callback.equals("null") ? callback : callback + ".right"; rightClickCallback = config.getString("rightClickCallback", rightClickCallback); + String middleClickCallback = callback.equals("null") ? callback : callback + ".middle"; + middleClickCallback = config.getString("middleClickCallback", middleClickCallback); unsigned slotOffset = config.getInt("slotOffset", 0); + String backingImage = config.getString("backingImage", ""); auto itemGrid = make_shared<ItemGridWidget>(ItemBagConstPtr(), dimensions, rowSpacing, columnSpacing, backingImage, slotOffset); - if (!m_callbacks.contains(callback)) - throw WidgetParserException::format("Failed to find itemgrid callback named: '{}'", callback); - - itemGrid->setCallback(m_callbacks.get(callback)); - itemGrid->setBackingImageAffinity( - config.getBool("showBackingImageWhenFull", false), config.getBool("showBackingImageWhenEmpty", true)); + config.getBool("showBackingImageWhenFull", false), config.getBool("showBackingImageWhenEmpty", true)); itemGrid->showDurability(config.getBool("showDurability", false)); - if (!m_callbacks.contains(rightClickCallback)) - throw WidgetParserException::format("Failed to find itemgrid rightClickCallback named: '{}'", rightClickCallback); + if (auto leftClickCallback = m_callbacks.ptr(callback)) + itemGrid->setCallback(*leftClickCallback); + else + throw WidgetParserException::format("Failed to find ItemGrid callback named: '{}'", callback); + + if (auto callback = m_callbacks.ptr(rightClickCallback)) + itemGrid->setRightClickCallback(*callback); + else + throw WidgetParserException::format("Failed to find ItemGrid rightClickCallback named: '{}'", rightClickCallback); - itemGrid->setRightClickCallback(m_callbacks.get(rightClickCallback)); + if (auto callback = m_callbacks.ptr(middleClickCallback)) + itemGrid->setMiddleClickCallback(*callback); common(itemGrid, config); |