Merge branch 'light-test'
This commit is contained in:
commit
f08ffe2162
BIN
assets/opensb/font/dotsies.woff2
Normal file
BIN
assets/opensb/font/dotsies.woff2
Normal file
Binary file not shown.
@ -1,21 +1,6 @@
|
|||||||
-- unused for now
|
|
||||||
|
|
||||||
local function modLight(light)
|
|
||||||
for i = 1, #light do
|
|
||||||
light[i] = light[i] * 0.4
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
function patch(object, path)
|
function patch(object, path)
|
||||||
if object.lightColor then
|
if object.pointLight ~= true and (object.lightColor or object.lightColors) then
|
||||||
modLight(object.lightColor)
|
object.lightType = "PointAsSpread"
|
||||||
object.pointLight = true
|
|
||||||
return object;
|
|
||||||
elseif object.lightColors then
|
|
||||||
for i, v in pairs(object.lightColors) do
|
|
||||||
modLight(v)
|
|
||||||
end
|
|
||||||
object.pointLight = true
|
|
||||||
return object;
|
return object;
|
||||||
end
|
end
|
||||||
end
|
end
|
@ -11,8 +11,8 @@ if assets.image("/cursors/cursors.png"):size()[1] == 64 then
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- Add object patches
|
-- Add object patches
|
||||||
--local objects = assets.byExtension("object")
|
local objects = assets.byExtension("object")
|
||||||
--local path = "/objects/opensb/object.patch.lua"
|
local path = "/objects/opensb/object.patch.lua"
|
||||||
--for i = 1, #objects do
|
for i = 1, #objects do
|
||||||
-- assets.patch(objects[i], path)
|
assets.patch(objects[i], path)
|
||||||
--end
|
end
|
@ -1,12 +1,13 @@
|
|||||||
#include "StarCellularLightArray.hpp"
|
#include "StarCellularLightArray.hpp"
|
||||||
|
#include "StarInterpolation.hpp"
|
||||||
// just specializing these in a cpp file so I can iterate on them without recompiling like 40 files!!
|
// just specializing these in a cpp file so I can iterate on them without recompiling like 40 files!!
|
||||||
|
|
||||||
namespace Star {
|
namespace Star {
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void CellularLightArray<ScalarLightTraits>::calculatePointLighting(size_t xmin, size_t ymin, size_t xmax, size_t ymax) {
|
void CellularLightArray<ScalarLightTraits>::calculatePointLighting(size_t xmin, size_t ymin, size_t xmax, size_t ymax) {
|
||||||
float perBlockObstacleAttenuation = 1.0f / m_pointMaxObstacle;
|
float pointPerBlockObstacleAttenuation = 1.0f / m_pointMaxObstacle;
|
||||||
float perBlockAirAttenuation = 1.0f / m_pointMaxAir;
|
float pointPerBlockAirAttenuation = 1.0f / m_pointMaxAir;
|
||||||
|
|
||||||
for (PointLight light : m_pointLights) {
|
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)
|
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);
|
float maxIntensity = ScalarLightTraits::maxIntensity(light.value);
|
||||||
Vec2F beamDirection = Vec2F(1, 0).rotate(light.beamAngle);
|
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
|
// The min / max considering the radius of the light
|
||||||
size_t lxmin = std::floor(std::max<float>(xmin, light.position[0] - maxRange));
|
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));
|
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;
|
continue;
|
||||||
|
|
||||||
Vec2F direction = relativeLightPosition / distance;
|
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);
|
attenuation += (1.0f - light.beamAmbience) * clamp(light.beam * (1.0f - direction * beamDirection), 0.0f, 1.0f);
|
||||||
if (attenuation >= 1.0f)
|
if (attenuation >= 1.0f)
|
||||||
continue;
|
continue;
|
||||||
@ -54,12 +57,21 @@ void CellularLightArray<ScalarLightTraits>::calculatePointLighting(size_t xmin,
|
|||||||
float circularizedPerBlockObstacleAttenuation = perBlockObstacleAttenuation / max(fabs(direction[0]), fabs(direction[1]));
|
float circularizedPerBlockObstacleAttenuation = perBlockObstacleAttenuation / max(fabs(direction[0]), fabs(direction[1]));
|
||||||
float blockAttenuation = lineAttenuation(blockPos, light.position, circularizedPerBlockObstacleAttenuation, remainingAttenuation);
|
float blockAttenuation = lineAttenuation(blockPos, light.position, circularizedPerBlockObstacleAttenuation, remainingAttenuation);
|
||||||
|
|
||||||
|
attenuation += blockAttenuation;
|
||||||
// Apply single obstacle boost (determine single obstacle by one
|
// Apply single obstacle boost (determine single obstacle by one
|
||||||
// block unit of attenuation).
|
// block unit of attenuation).
|
||||||
attenuation += blockAttenuation + min(blockAttenuation, circularizedPerBlockObstacleAttenuation) * m_pointObstacleBoost;
|
if (!light.asSpread)
|
||||||
|
attenuation += min(blockAttenuation, circularizedPerBlockObstacleAttenuation) * m_pointObstacleBoost;
|
||||||
|
|
||||||
if (attenuation < 1.0f)
|
if (attenuation < 1.0f) {
|
||||||
setLight(x, y, lvalue + ScalarLightTraits::subtract(light.value, attenuation));
|
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 <>
|
template <>
|
||||||
void CellularLightArray<ColoredLightTraits>::calculatePointLighting(size_t xmin, size_t ymin, size_t xmax, size_t ymax) {
|
void CellularLightArray<ColoredLightTraits>::calculatePointLighting(size_t xmin, size_t ymin, size_t xmax, size_t ymax) {
|
||||||
float perBlockObstacleAttenuation = 1.0f / m_pointMaxObstacle;
|
float pointPerBlockObstacleAttenuation = 1.0f / m_pointMaxObstacle;
|
||||||
float perBlockAirAttenuation = 1.0f / m_pointMaxAir;
|
float pointPerBlockAirAttenuation = 1.0f / m_pointMaxAir;
|
||||||
|
|
||||||
for (PointLight light : m_pointLights) {
|
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)
|
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);
|
float maxIntensity = ColoredLightTraits::maxIntensity(light.value);
|
||||||
Vec2F beamDirection = Vec2F(1, 0).rotate(light.beamAngle);
|
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
|
// The min / max considering the radius of the light
|
||||||
size_t lxmin = std::floor(std::max<float>(xmin, light.position[0] - maxRange));
|
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));
|
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 circularizedPerBlockObstacleAttenuation = perBlockObstacleAttenuation / max(fabs(direction[0]), fabs(direction[1]));
|
||||||
float blockAttenuation = lineAttenuation(blockPos, light.position, circularizedPerBlockObstacleAttenuation, remainingAttenuation);
|
float blockAttenuation = lineAttenuation(blockPos, light.position, circularizedPerBlockObstacleAttenuation, remainingAttenuation);
|
||||||
|
|
||||||
|
attenuation += blockAttenuation;
|
||||||
// Apply single obstacle boost (determine single obstacle by one
|
// Apply single obstacle boost (determine single obstacle by one
|
||||||
// block unit of attenuation).
|
// block unit of attenuation).
|
||||||
attenuation += blockAttenuation + min(blockAttenuation, circularizedPerBlockObstacleAttenuation) * m_pointObstacleBoost;
|
if (!light.asSpread)
|
||||||
|
attenuation += min(blockAttenuation, circularizedPerBlockObstacleAttenuation) * m_pointObstacleBoost;
|
||||||
|
|
||||||
if (attenuation < 1.0f)
|
if (attenuation < 1.0f) {
|
||||||
setLight(x, y, lvalue + ColoredLightTraits::subtract(light.value, attenuation));
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,6 +56,7 @@ public:
|
|||||||
float beam;
|
float beam;
|
||||||
float beamAngle;
|
float beamAngle;
|
||||||
float beamAmbience;
|
float beamAmbience;
|
||||||
|
bool asSpread;
|
||||||
};
|
};
|
||||||
|
|
||||||
void setParameters(unsigned spreadPasses, float spreadMaxAir, float spreadMaxObstacle,
|
void setParameters(unsigned spreadPasses, float spreadMaxAir, float spreadMaxObstacle,
|
||||||
|
@ -109,12 +109,12 @@ void CellularLightingCalculator::addSpreadLight(Vec2F const& position, Vec3F con
|
|||||||
m_lightArray.left().addSpreadLight({arrayPosition, light});
|
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());
|
Vec2F arrayPosition = position - Vec2F(m_calculationRegion.min());
|
||||||
if (m_monochrome)
|
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
|
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) {
|
void CellularLightingCalculator::calculate(Image& output) {
|
||||||
|
@ -136,7 +136,7 @@ public:
|
|||||||
void setCellIndex(size_t cellIndex, Vec3F const& light, bool obstacle);
|
void setCellIndex(size_t cellIndex, Vec3F const& light, bool obstacle);
|
||||||
|
|
||||||
void addSpreadLight(Vec2F const& position, Vec3F const& light);
|
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
|
// 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
|
// output image. The image will be reset to the size of the region given in
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#include "StarJsonExtra.hpp"
|
#include "StarJsonExtra.hpp"
|
||||||
#include "StarStatistics.hpp"
|
#include "StarStatistics.hpp"
|
||||||
#include "StarAugmentItem.hpp"
|
#include "StarAugmentItem.hpp"
|
||||||
|
#include "StarObjectItem.hpp"
|
||||||
|
#include "StarInteractionTypes.hpp"
|
||||||
|
|
||||||
namespace Star {
|
namespace Star {
|
||||||
|
|
||||||
@ -94,6 +96,27 @@ InventoryPane::InventoryPane(MainInterface* parent, PlayerPtr player, ContainerI
|
|||||||
rightClickCallback(slot);
|
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");
|
Json itemBagConfig = config.get("bagConfig");
|
||||||
auto bagOrder = itemBagConfig.toObject().keys().sorted([&itemBagConfig](String const& a, String const& b) {
|
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);
|
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");
|
auto itemGrid = itemBagConfig.get(name).getString("itemGrid");
|
||||||
invWindowReader.registerCallback(itemGrid, bind(leftClickCallback, name, _1));
|
invWindowReader.registerCallback(itemGrid, bind(leftClickCallback, name, _1));
|
||||||
invWindowReader.registerCallback(strf("{}.right", itemGrid), bind(bagGridCallback, name, _1));
|
invWindowReader.registerCallback(strf("{}.right", itemGrid), bind(bagGridCallback, name, _1));
|
||||||
|
invWindowReader.registerCallback(strf("{}.middle", itemGrid), bind(middleClickCallback, name, _1));
|
||||||
}
|
}
|
||||||
|
|
||||||
invWindowReader.registerCallback("close", [=](Widget*) {
|
invWindowReader.registerCallback("close", [=](Widget*) {
|
||||||
|
@ -199,6 +199,9 @@ bool MainInterface::escapeDialogOpen() const {
|
|||||||
void MainInterface::openCraftingWindow(Json const& config, EntityId sourceEntityId) {
|
void MainInterface::openCraftingWindow(Json const& config, EntityId sourceEntityId) {
|
||||||
if (m_craftingWindow && m_paneManager.isDisplayed(m_craftingWindow)) {
|
if (m_craftingWindow && m_paneManager.isDisplayed(m_craftingWindow)) {
|
||||||
m_paneManager.dismissPane(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) {
|
if (m_craftingWindow->sourceEntityId() == sourceEntityId) {
|
||||||
m_craftingWindow.reset();
|
m_craftingWindow.reset();
|
||||||
return;
|
return;
|
||||||
@ -215,21 +218,27 @@ void MainInterface::openCraftingWindow(Json const& config, EntityId sourceEntity
|
|||||||
void MainInterface::openMerchantWindow(Json const& config, EntityId sourceEntityId) {
|
void MainInterface::openMerchantWindow(Json const& config, EntityId sourceEntityId) {
|
||||||
if (m_merchantWindow && m_paneManager.isDisplayed(m_merchantWindow)) {
|
if (m_merchantWindow && m_paneManager.isDisplayed(m_merchantWindow)) {
|
||||||
m_paneManager.dismissPane(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();
|
m_merchantWindow.reset();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool openWithInventory = config.getBool("openWithInventory", true);
|
||||||
m_merchantWindow = make_shared<MerchantPane>(m_client->worldClient(), m_client->mainPlayer(), config, sourceEntityId);
|
m_merchantWindow = make_shared<MerchantPane>(m_client->worldClient(), m_client->mainPlayer(), config, sourceEntityId);
|
||||||
m_paneManager.displayPane(PaneLayer::Window,
|
m_paneManager.displayPane(PaneLayer::Window,
|
||||||
m_merchantWindow,
|
m_merchantWindow,
|
||||||
[this](PanePtr const&) {
|
[this, openWithInventory](PanePtr const&) {
|
||||||
if (auto player = m_client->mainPlayer())
|
if (auto player = m_client->mainPlayer())
|
||||||
player->clearSwap();
|
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_paneManager.bringPaneAdjacent(m_paneManager.registeredPane(MainInterfacePanes::Inventory),
|
||||||
m_merchantWindow, Root::singleton().assets()->json("/interface.config:bringAdjacentWindowGap").toFloat());
|
m_merchantWindow, Root::singleton().assets()->json("/interface.config:bringAdjacentWindowGap").toFloat());
|
||||||
|
@ -320,7 +320,7 @@ void ItemDrop::render(RenderCallback* renderCallback) {
|
|||||||
|
|
||||||
void ItemDrop::renderLightSources(RenderCallback* renderCallback) {
|
void ItemDrop::renderLightSources(RenderCallback* renderCallback) {
|
||||||
LightSource light;
|
LightSource light;
|
||||||
light.pointLight = false;
|
light.type = LightType::Spread;
|
||||||
light.color = Vec3F::filled(20.f / 255.f);
|
light.color = Vec3F::filled(20.f / 255.f);
|
||||||
light.position = position();
|
light.position = position();
|
||||||
renderCallback->addLightSource(std::move(light));
|
renderCallback->addLightSource(std::move(light));
|
||||||
|
@ -3,6 +3,12 @@
|
|||||||
|
|
||||||
namespace Star {
|
namespace Star {
|
||||||
|
|
||||||
|
EnumMap<LightType> const LightTypeNames{
|
||||||
|
{LightType::Spread, "Spread"},
|
||||||
|
{LightType::Point, "Point"},
|
||||||
|
{LightType::PointAsSpread, "PointAsSpread"}
|
||||||
|
};
|
||||||
|
|
||||||
void LightSource::translate(Vec2F const& pos) {
|
void LightSource::translate(Vec2F const& pos) {
|
||||||
position += pos;
|
position += pos;
|
||||||
}
|
}
|
||||||
@ -10,7 +16,7 @@ void LightSource::translate(Vec2F const& pos) {
|
|||||||
DataStream& operator<<(DataStream& ds, LightSource const& lightSource) {
|
DataStream& operator<<(DataStream& ds, LightSource const& lightSource) {
|
||||||
ds.write(lightSource.position);
|
ds.write(lightSource.position);
|
||||||
ds.write(lightSource.color);
|
ds.write(lightSource.color);
|
||||||
ds.write(lightSource.pointLight);
|
ds.write(lightSource.type);
|
||||||
ds.write(lightSource.pointBeam);
|
ds.write(lightSource.pointBeam);
|
||||||
ds.write(lightSource.beamAngle);
|
ds.write(lightSource.beamAngle);
|
||||||
ds.write(lightSource.beamAmbience);
|
ds.write(lightSource.beamAmbience);
|
||||||
@ -21,7 +27,7 @@ DataStream& operator<<(DataStream& ds, LightSource const& lightSource) {
|
|||||||
DataStream& operator>>(DataStream& ds, LightSource& lightSource) {
|
DataStream& operator>>(DataStream& ds, LightSource& lightSource) {
|
||||||
ds.read(lightSource.position);
|
ds.read(lightSource.position);
|
||||||
ds.read(lightSource.color);
|
ds.read(lightSource.color);
|
||||||
ds.read(lightSource.pointLight);
|
ds.read(lightSource.type);
|
||||||
ds.read(lightSource.pointBeam);
|
ds.read(lightSource.pointBeam);
|
||||||
ds.read(lightSource.beamAngle);
|
ds.read(lightSource.beamAngle);
|
||||||
ds.read(lightSource.beamAmbience);
|
ds.read(lightSource.beamAmbience);
|
||||||
|
@ -2,14 +2,22 @@
|
|||||||
|
|
||||||
#include "StarVector.hpp"
|
#include "StarVector.hpp"
|
||||||
#include "StarDataStream.hpp"
|
#include "StarDataStream.hpp"
|
||||||
|
#include "StarBiMap.hpp"
|
||||||
|
|
||||||
namespace Star {
|
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 {
|
struct LightSource {
|
||||||
Vec2F position;
|
Vec2F position;
|
||||||
Vec3F color;
|
Vec3F color;
|
||||||
|
LightType type;
|
||||||
bool pointLight;
|
|
||||||
// pointBeam of 0.0 means light has no beam component, as pointBeam goes up,
|
// pointBeam of 0.0 means light has no beam component, as pointBeam goes up,
|
||||||
// the dropoff from the beamAngle becomes faster and faster.
|
// the dropoff from the beamAngle becomes faster and faster.
|
||||||
float pointBeam;
|
float pointBeam;
|
||||||
|
@ -379,7 +379,7 @@ CollisionKind MaterialDatabase::materialCollisionKind(MaterialId materialId) con
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool MaterialDatabase::canPlaceInLayer(MaterialId materialId, TileLayer layer) const {
|
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 {
|
ItemDescriptor MaterialDatabase::materialItemDrop(MaterialId materialId) const {
|
||||||
|
@ -717,7 +717,7 @@ List<LightSource> NetworkedAnimator::lightSources(Vec2F const& translate) const
|
|||||||
lightSources.append(LightSource{
|
lightSources.append(LightSource{
|
||||||
position + translate,
|
position + translate,
|
||||||
color.toRgbF(),
|
color.toRgbF(),
|
||||||
pair.second.pointLight,
|
pair.second.pointLight ? LightType::Point : LightType::Spread,
|
||||||
pair.second.pointBeam,
|
pair.second.pointBeam,
|
||||||
pointAngle,
|
pointAngle,
|
||||||
pair.second.beamAmbience
|
pair.second.beamAmbience
|
||||||
|
@ -262,7 +262,7 @@ List<LightSource> Object::lightSources() const {
|
|||||||
LightSource lightSource;
|
LightSource lightSource;
|
||||||
lightSource.position = position() + centerOfTile(orientation->lightPosition);
|
lightSource.position = position() + centerOfTile(orientation->lightPosition);
|
||||||
lightSource.color = color.toRgbF();
|
lightSource.color = color.toRgbF();
|
||||||
lightSource.pointLight = m_config->pointLight;
|
lightSource.type = m_config->lightType;
|
||||||
lightSource.pointBeam = m_config->pointBeam;
|
lightSource.pointBeam = m_config->pointBeam;
|
||||||
lightSource.beamAngle = orientation->beamAngle;
|
lightSource.beamAngle = orientation->beamAngle;
|
||||||
lightSource.beamAmbience = m_config->beamAmbience;
|
lightSource.beamAmbience = m_config->beamAmbience;
|
||||||
|
@ -495,7 +495,10 @@ ObjectConfigPtr ObjectDatabase::readConfig(String const& path) {
|
|||||||
objectConfig->lightColors[pair.first] = jsonToColor(pair.second);
|
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->pointBeam = config.getFloat("pointBeam", 0.0f);
|
||||||
objectConfig->beamAmbience = config.getFloat("beamAmbience", 0.0f);
|
objectConfig->beamAmbience = config.getFloat("beamAmbience", 0.0f);
|
||||||
|
|
||||||
|
@ -131,7 +131,7 @@ struct ObjectConfig {
|
|||||||
bool interactive;
|
bool interactive;
|
||||||
|
|
||||||
StringMap<Color> lightColors;
|
StringMap<Color> lightColors;
|
||||||
bool pointLight;
|
LightType lightType;
|
||||||
float pointBeam;
|
float pointBeam;
|
||||||
float beamAmbience;
|
float beamAmbience;
|
||||||
Maybe<PeriodicFunction<float>> lightFlickering;
|
Maybe<PeriodicFunction<float>> lightFlickering;
|
||||||
|
@ -379,7 +379,7 @@ void Projectile::renderLightSources(RenderCallback* renderCallback) {
|
|||||||
if (renderable.is<LightSource>())
|
if (renderable.is<LightSource>())
|
||||||
renderCallback->addLightSource(renderable.get<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) {
|
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{
|
m_pendingRenderables.append(LightSource{
|
||||||
position(),
|
position(),
|
||||||
jsonToColor(parameters.get("color")).toRgbF(),
|
jsonToColor(parameters.get("color")).toRgbF(),
|
||||||
parameters.getBool("pointLight", true),
|
(LightType)parameters.getBool("pointLight", true),
|
||||||
0.0f,
|
0.0f,
|
||||||
0.0f,
|
0.0f,
|
||||||
0.0f
|
0.0f
|
||||||
|
@ -118,7 +118,10 @@ ProjectileConfigPtr ProjectileDatabase::readConfig(String const& path) {
|
|||||||
|
|
||||||
projectileConfig->lightColor = jsonToColor(config.get("lightColor", JsonArray{0, 0, 0}));
|
projectileConfig->lightColor = jsonToColor(config.get("lightColor", JsonArray{0, 0, 0}));
|
||||||
projectileConfig->lightPosition = jsonToVec2F(config.get("lightPosition", JsonArray{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", "");
|
projectileConfig->persistentAudio = config.getString("persistentAudio", "");
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ struct ProjectileConfig {
|
|||||||
|
|
||||||
Color lightColor;
|
Color lightColor;
|
||||||
Vec2F lightPosition;
|
Vec2F lightPosition;
|
||||||
bool pointLight = false;
|
LightType lightType = LightType::Spread;
|
||||||
|
|
||||||
String persistentAudio;
|
String persistentAudio;
|
||||||
|
|
||||||
|
@ -1650,14 +1650,14 @@ void UniverseServer::acceptConnection(UniverseConnection connection, Maybe<HostA
|
|||||||
WriteLocker clientsLocker(m_clientsLock);
|
WriteLocker clientsLocker(m_clientsLock);
|
||||||
if (auto clashId = getClientForUuid(clientConnect->playerUuid)) {
|
if (auto clashId = getClientForUuid(clientConnect->playerUuid)) {
|
||||||
if (administrator) {
|
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 {
|
} else {
|
||||||
connectionFail("Duplicate player UUID");
|
connectionFail("Duplicate player UUID");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_clients.size() + 1 > m_maxPlayers) {
|
if (m_clients.size() + 1 > m_maxPlayers && !administrator) {
|
||||||
connectionFail("Max player connections");
|
connectionFail("Max player connections");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1734,8 +1734,14 @@ void UniverseServer::acceptConnection(UniverseConnection connection, Maybe<HostA
|
|||||||
clientWarpPlayer(clientId, WarpAlias::OwnShip);
|
clientWarpPlayer(clientId, WarpAlias::OwnShip);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Logger::info("UniverseServer: Spawning player at ship");
|
Maybe<String> defaultReviveWarp = assets->json("/universe_server.config").optString("defaultReviveWarp");
|
||||||
clientWarpPlayer(clientId, WarpAlias::OwnShip);
|
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());
|
clientFlyShip(clientId, clientContext->shipCoordinate().location(), clientContext->shipLocation());
|
||||||
|
@ -1652,10 +1652,15 @@ void WorldClient::lightingCalc() {
|
|||||||
|
|
||||||
for (auto const& light : lights) {
|
for (auto const& light : lights) {
|
||||||
Vec2F position = m_geometry.nearestTo(Vec2F(m_lightingCalculator.calculationRegion().min()), light.position);
|
Vec2F position = m_geometry.nearestTo(Vec2F(m_lightingCalculator.calculationRegion().min()), light.position);
|
||||||
if (light.pointLight)
|
if (light.type == LightType::Spread)
|
||||||
m_lightingCalculator.addPointLight(position, light.color, light.pointBeam, light.beamAngle, light.beamAmbience);
|
|
||||||
else {
|
|
||||||
m_lightingCalculator.addSpreadLight(position, light.color);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -445,10 +445,10 @@ namespace WorldImpl {
|
|||||||
for (auto const& entity : entityMap->entityQuery(RectF(lighting.calculationRegion()))) {
|
for (auto const& entity : entityMap->entityQuery(RectF(lighting.calculationRegion()))) {
|
||||||
for (auto const& light : entity->lightSources()) {
|
for (auto const& light : entity->lightSources()) {
|
||||||
Vec2F position = worldGeometry.nearestTo(Vec2F(lighting.calculationRegion().min()), light.position);
|
Vec2F position = worldGeometry.nearestTo(Vec2F(lighting.calculationRegion().min()), light.position);
|
||||||
if (light.pointLight)
|
if (light.type == LightType::Spread)
|
||||||
lighting.addPointLight(position, light.color.sum() / 3.0f, light.pointBeam, light.beamAngle, light.beamAmbience);
|
|
||||||
else
|
|
||||||
lighting.addSpreadLight(position, light.color.sum() / 3.0f);
|
lighting.addSpreadLight(position, light.color.sum() / 3.0f);
|
||||||
|
else
|
||||||
|
lighting.addPointLight(position, light.color.sum() / 3.0f, light.pointBeam, light.beamAngle, light.beamAmbience);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ List<LightSource> InspectionTool::lightSources() const {
|
|||||||
|
|
||||||
float angle = world()->geometry().diff(owner()->aimPosition(), owner()->position()).angle();
|
float angle = world()->geometry().diff(owner()->aimPosition(), owner()->position()).angle();
|
||||||
LightSource lightSource;
|
LightSource lightSource;
|
||||||
lightSource.pointLight = true;
|
lightSource.type = LightType::Point;
|
||||||
lightSource.position = owner()->position() + owner()->handPosition(hand(), m_lightPosition - m_handPosition);
|
lightSource.position = owner()->position() + owner()->handPosition(hand(), m_lightPosition - m_handPosition);
|
||||||
lightSource.color = m_lightColor.toRgbF();
|
lightSource.color = m_lightColor.toRgbF();
|
||||||
lightSource.pointBeam = m_beamWidth;
|
lightSource.pointBeam = m_beamWidth;
|
||||||
|
@ -239,7 +239,7 @@ List<LightSource> Flashlight::lightSources() const {
|
|||||||
|
|
||||||
float angle = world()->geometry().diff(owner()->aimPosition(), owner()->position()).angle();
|
float angle = world()->geometry().diff(owner()->aimPosition(), owner()->position()).angle();
|
||||||
LightSource lightSource;
|
LightSource lightSource;
|
||||||
lightSource.pointLight = true;
|
lightSource.type = LightType::Point;
|
||||||
lightSource.position = owner()->position() + owner()->handPosition(hand(), (m_lightPosition - m_handPosition) / TilePixels);
|
lightSource.position = owner()->position() + owner()->handPosition(hand(), (m_lightPosition - m_handPosition) / TilePixels);
|
||||||
lightSource.color = m_lightColor.toRgbF();
|
lightSource.color = m_lightColor.toRgbF();
|
||||||
lightSource.pointBeam = m_beamWidth;
|
lightSource.pointBeam = m_beamWidth;
|
||||||
|
@ -77,7 +77,7 @@ LuaAnimationComponent<Base>::LuaAnimationComponent() {
|
|||||||
m_lightSources.append({
|
m_lightSources.append({
|
||||||
lightSourceTable.get<Vec2F>("position"),
|
lightSourceTable.get<Vec2F>("position"),
|
||||||
lightSourceTable.get<Color>("color").toRgbF(),
|
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>>("pointBeam").value(),
|
||||||
lightSourceTable.get<Maybe<float>>("beamAngle").value(),
|
lightSourceTable.get<Maybe<float>>("beamAngle").value(),
|
||||||
lightSourceTable.get<Maybe<float>>("beamAmbience").value()
|
lightSourceTable.get<Maybe<float>>("beamAmbience").value()
|
||||||
|
@ -106,7 +106,9 @@ Vec2I ItemGridWidget::positionOfSlot(size_t slotNumber) {
|
|||||||
bool ItemGridWidget::sendEvent(InputEvent const& event) {
|
bool ItemGridWidget::sendEvent(InputEvent const& event) {
|
||||||
if (m_visible) {
|
if (m_visible) {
|
||||||
if (auto mouseButton = event.ptr<MouseButtonDownEvent>()) {
|
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);
|
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) {
|
for (size_t i = 0; i < (m_bag->size() - m_bagOffset) && i < unsigned(m_dimensions[0] * m_dimensions[1]); ++i) {
|
||||||
Vec2I loc = locOfItemSlot(i);
|
Vec2I loc = locOfItemSlot(i);
|
||||||
@ -116,6 +118,8 @@ bool ItemGridWidget::sendEvent(InputEvent const& event) {
|
|||||||
m_selectedIndex = i;
|
m_selectedIndex = i;
|
||||||
if (mouseButton->mouseButton == MouseButton::Right)
|
if (mouseButton->mouseButton == MouseButton::Right)
|
||||||
m_rightClickCallback(this);
|
m_rightClickCallback(this);
|
||||||
|
else if (mouseButton->mouseButton == MouseButton::Middle)
|
||||||
|
m_middleClickCallback(this);
|
||||||
else
|
else
|
||||||
m_callback(this);
|
m_callback(this);
|
||||||
return true;
|
return true;
|
||||||
@ -145,6 +149,10 @@ void ItemGridWidget::setRightClickCallback(WidgetCallbackFunc callback) {
|
|||||||
m_rightClickCallback = callback;
|
m_rightClickCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ItemGridWidget::setMiddleClickCallback(WidgetCallbackFunc callback) {
|
||||||
|
m_middleClickCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
void ItemGridWidget::setItemBag(ItemBagConstPtr bag) {
|
void ItemGridWidget::setItemBag(ItemBagConstPtr bag) {
|
||||||
m_bag = bag;
|
m_bag = bag;
|
||||||
|
|
||||||
|
@ -41,6 +41,7 @@ public:
|
|||||||
bool sendEvent(InputEvent const& event) override;
|
bool sendEvent(InputEvent const& event) override;
|
||||||
void setCallback(WidgetCallbackFunc callback);
|
void setCallback(WidgetCallbackFunc callback);
|
||||||
void setRightClickCallback(WidgetCallbackFunc callback);
|
void setRightClickCallback(WidgetCallbackFunc callback);
|
||||||
|
void setMiddleClickCallback(WidgetCallbackFunc callback);
|
||||||
void setItemBag(ItemBagConstPtr bag);
|
void setItemBag(ItemBagConstPtr bag);
|
||||||
void setProgress(float progress);
|
void setProgress(float progress);
|
||||||
|
|
||||||
@ -93,6 +94,7 @@ private:
|
|||||||
unsigned m_selectedIndex;
|
unsigned m_selectedIndex;
|
||||||
WidgetCallbackFunc m_callback;
|
WidgetCallbackFunc m_callback;
|
||||||
WidgetCallbackFunc m_rightClickCallback;
|
WidgetCallbackFunc m_rightClickCallback;
|
||||||
|
WidgetCallbackFunc m_middleClickCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -67,12 +67,16 @@ void ItemSlotWidget::update(float dt) {
|
|||||||
bool ItemSlotWidget::sendEvent(InputEvent const& event) {
|
bool ItemSlotWidget::sendEvent(InputEvent const& event) {
|
||||||
if (m_visible) {
|
if (m_visible) {
|
||||||
if (auto mouseButton = event.ptr<MouseButtonDownEvent>()) {
|
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);
|
Vec2I mousePos = *context()->mousePosition(event);
|
||||||
RectI itemArea = m_itemDraggableArea.translated(screenPosition());
|
RectI itemArea = m_itemDraggableArea.translated(screenPosition());
|
||||||
if (itemArea.contains(mousePos)) {
|
if (itemArea.contains(mousePos)) {
|
||||||
if (mouseButton->mouseButton == MouseButton::Right)
|
if (mouseButton->mouseButton == MouseButton::Right)
|
||||||
m_rightClickCallback(this);
|
m_rightClickCallback(this);
|
||||||
|
else if (mouseButton->mouseButton == MouseButton::Middle)
|
||||||
|
m_middleClickCallback(this);
|
||||||
else
|
else
|
||||||
m_callback(this);
|
m_callback(this);
|
||||||
return true;
|
return true;
|
||||||
@ -92,6 +96,10 @@ void ItemSlotWidget::setRightClickCallback(WidgetCallbackFunc callback) {
|
|||||||
m_rightClickCallback = callback;
|
m_rightClickCallback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ItemSlotWidget::setMiddleClickCallback(WidgetCallbackFunc callback) {
|
||||||
|
m_middleClickCallback = callback;
|
||||||
|
}
|
||||||
|
|
||||||
void ItemSlotWidget::setItem(ItemPtr const& item) {
|
void ItemSlotWidget::setItem(ItemPtr const& item) {
|
||||||
m_item = item;
|
m_item = item;
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ public:
|
|||||||
bool sendEvent(InputEvent const& event) override;
|
bool sendEvent(InputEvent const& event) override;
|
||||||
void setCallback(WidgetCallbackFunc callback);
|
void setCallback(WidgetCallbackFunc callback);
|
||||||
void setRightClickCallback(WidgetCallbackFunc callback);
|
void setRightClickCallback(WidgetCallbackFunc callback);
|
||||||
|
void setMiddleClickCallback(WidgetCallbackFunc callback);
|
||||||
void setItem(ItemPtr const& item);
|
void setItem(ItemPtr const& item);
|
||||||
ItemPtr item() const;
|
ItemPtr item() const;
|
||||||
void setProgress(float progress);
|
void setProgress(float progress);
|
||||||
@ -61,6 +62,7 @@ private:
|
|||||||
|
|
||||||
WidgetCallbackFunc m_callback;
|
WidgetCallbackFunc m_callback;
|
||||||
WidgetCallbackFunc m_rightClickCallback;
|
WidgetCallbackFunc m_rightClickCallback;
|
||||||
|
WidgetCallbackFunc m_middleClickCallback;
|
||||||
float m_progress;
|
float m_progress;
|
||||||
|
|
||||||
ProgressWidgetPtr m_durabilityBar;
|
ProgressWidgetPtr m_durabilityBar;
|
||||||
|
@ -471,23 +471,27 @@ WidgetConstructResult WidgetParser::itemSlotHandler(String const& name, Json con
|
|||||||
String backingImage = config.getString("backingImage", "");
|
String backingImage = config.getString("backingImage", "");
|
||||||
String callback = config.getString("callback", name);
|
String callback = config.getString("callback", name);
|
||||||
|
|
||||||
String rightClickCallback;
|
String rightClickCallback = callback.equals("null") ? callback : callback + ".right";
|
||||||
if (callback.equals("null"))
|
|
||||||
rightClickCallback = callback;
|
|
||||||
else
|
|
||||||
rightClickCallback = callback + ".right";
|
|
||||||
rightClickCallback = config.getString("rightClickCallback", rightClickCallback);
|
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);
|
auto itemSlot = make_shared<ItemSlotWidget>(ItemPtr(), backingImage);
|
||||||
|
|
||||||
if (!m_callbacks.contains(callback))
|
if (auto leftClickCallback = m_callbacks.ptr(callback))
|
||||||
throw WidgetParserException::format("Failed to find itemSlot callback named: '{}'", callback);
|
itemSlot->setCallback(*leftClickCallback);
|
||||||
itemSlot->setCallback(m_callbacks.get(callback));
|
else
|
||||||
|
throw WidgetParserException::format("Failed to find ItemSlot callback named: '{}'", callback);
|
||||||
|
|
||||||
if (!m_callbacks.contains(rightClickCallback))
|
if (auto callback = m_callbacks.ptr(rightClickCallback))
|
||||||
throw WidgetParserException::format("Failed to find itemslot rightClickCallback named: '{}'", 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->setBackingImageAffinity(config.getBool("showBackingImageWhenFull", false), config.getBool("showBackingImageWhenEmpty", true));
|
||||||
itemSlot->showDurability(config.getBool("showDurability", false));
|
itemSlot->showDurability(config.getBool("showDurability", false));
|
||||||
itemSlot->showCount(config.getBool("showCount", true));
|
itemSlot->showCount(config.getBool("showCount", true));
|
||||||
@ -516,32 +520,33 @@ WidgetConstructResult WidgetParser::itemGridHandler(String const& name, Json con
|
|||||||
throw WidgetParserException::format("Malformed gui json, missing a required value in the map. {}", outputException(e, false));
|
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 callback = config.getString("callback", name);
|
||||||
String rightClickCallback;
|
String rightClickCallback = callback.equals("null") ? callback : callback + ".right";
|
||||||
if (callback.equals("null"))
|
|
||||||
rightClickCallback = callback;
|
|
||||||
else
|
|
||||||
rightClickCallback = callback + ".right";
|
|
||||||
rightClickCallback = config.getString("rightClickCallback", rightClickCallback);
|
rightClickCallback = config.getString("rightClickCallback", rightClickCallback);
|
||||||
|
String middleClickCallback = callback.equals("null") ? callback : callback + ".middle";
|
||||||
|
middleClickCallback = config.getString("middleClickCallback", middleClickCallback);
|
||||||
|
|
||||||
unsigned slotOffset = config.getInt("slotOffset", 0);
|
unsigned slotOffset = config.getInt("slotOffset", 0);
|
||||||
|
String backingImage = config.getString("backingImage", "");
|
||||||
|
|
||||||
auto itemGrid = make_shared<ItemGridWidget>(ItemBagConstPtr(), dimensions, rowSpacing, columnSpacing, backingImage, slotOffset);
|
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(
|
itemGrid->setBackingImageAffinity(
|
||||||
config.getBool("showBackingImageWhenFull", false), config.getBool("showBackingImageWhenEmpty", true));
|
config.getBool("showBackingImageWhenFull", false), config.getBool("showBackingImageWhenEmpty", true));
|
||||||
itemGrid->showDurability(config.getBool("showDurability", false));
|
itemGrid->showDurability(config.getBool("showDurability", false));
|
||||||
|
|
||||||
if (!m_callbacks.contains(rightClickCallback))
|
if (auto leftClickCallback = m_callbacks.ptr(callback))
|
||||||
throw WidgetParserException::format("Failed to find itemgrid rightClickCallback named: '{}'", rightClickCallback);
|
itemGrid->setCallback(*leftClickCallback);
|
||||||
|
else
|
||||||
|
throw WidgetParserException::format("Failed to find ItemGrid callback named: '{}'", callback);
|
||||||
|
|
||||||
itemGrid->setRightClickCallback(m_callbacks.get(rightClickCallback));
|
if (auto callback = m_callbacks.ptr(rightClickCallback))
|
||||||
|
itemGrid->setRightClickCallback(*callback);
|
||||||
|
else
|
||||||
|
throw WidgetParserException::format("Failed to find ItemGrid rightClickCallback named: '{}'", rightClickCallback);
|
||||||
|
|
||||||
|
if (auto callback = m_callbacks.ptr(middleClickCallback))
|
||||||
|
itemGrid->setMiddleClickCallback(*callback);
|
||||||
|
|
||||||
common(itemGrid, config);
|
common(itemGrid, config);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user