1
0
forked from 0ad/0ad

Fix [19027] by using generic code for conversions and fixing a few other issues. Refs #3403. Reviewed by leper.

Also fix some of the warnings that jenkins showed.

Differential Revision: https://code.wildfiregames.com/D24
This was SVN commit r19115.
This commit is contained in:
wraitii 2017-01-06 11:14:03 +00:00
parent 1a038b1735
commit 2bae30c454
7 changed files with 178 additions and 214 deletions

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2016 Wildfire Games.
/* Copyright (C) 2017 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -38,6 +38,15 @@ CChart::~CChart()
void CChart::HandleMessage(SGUIMessage& Message)
{
// TODO: implement zoom
switch (Message.type)
{
case GUIM_SETTINGS_UPDATED:
{
UpdateSeries();
break;
}
}
}
void CChart::Draw()
@ -47,16 +56,14 @@ void CChart::Draw()
if (!GetGUI())
return;
UpdateSeries();
if (m_Series.empty())
return;
const float bz = GetBufferedZ();
CRect rect = GetChartRect();
const float width = rect.GetWidth();
const float height = rect.GetHeight();
if (m_Series.empty())
return;
// Disable depth updates to prevent apparent z-fighting-related issues
// with some drivers causing units to get drawn behind the texture.
glDepthMask(0);
@ -93,6 +100,7 @@ void CChart::Draw()
continue;
std::vector<float> vertices;
vertices.reserve(data.m_Points.size() * 3);
for (const CVector2D& point : data.m_Points)
{
vertices.push_back(rect.left + (point.X - leftBottom.X) * scale.X);
@ -131,10 +139,10 @@ void CChart::UpdateSeries()
GUI<CGUIList>::GetSettingPointer(this, "series_color", pSeriesColor);
m_Series.clear();
m_Series.resize(pSeries->m_Series.size());
for (size_t i = 0; i < pSeries->m_Series.size(); ++i)
{
m_Series.resize(m_Series.size() + 1);
CChartData& data = m_Series.back();
CChartData& data = m_Series[i];
if (i < pSeriesColor->m_Items.size() && !GUI<int>::ParseColor(pSeriesColor->m_Items[i].GetOriginalString(), data.m_Color, 0))
LOGWARNING("GUI: Error parsing 'series_color' (\"%s\")", utf8_from_wstring(pSeriesColor->m_Items[i].GetOriginalString()));

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2016 Wildfire Games.
/* Copyright (C) 2017 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -29,4 +29,4 @@ public:
std::vector<std::vector<CVector2D>> m_Series;
};
#endif
#endif // INCLUDED_CGUISERIES

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2016 Wildfire Games.
/* Copyright (C) 2017 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -17,11 +17,12 @@
#include "precompiled.h"
#include "scriptinterface/ScriptInterface.h"
#include "scriptinterface/ScriptConversions.h"
#include "gui/IGUIObject.h"
#include "lib/external_libraries/libsdl.h"
#include "ps/Hotkey.h"
#include "maths/Vector2D.h"
#define SET(obj, name, value) STMT(JS::RootedValue v_(cx); AssignOrToJSVal(cx, &v_, (value)); JS_SetProperty(cx, obj, (name), v_))
// ignore JS_SetProperty return value, because errors should be impossible
@ -121,3 +122,23 @@ template<> void ScriptInterface::ToJSVal<IGUIObject*>(JSContext* UNUSED(cx), JS:
else
ret.setObject(*val->GetJSObject());
}
template<> void ScriptInterface::ToJSVal<CGUIString>(JSContext* cx, JS::MutableHandleValue ret, const CGUIString& val)
{
ScriptInterface::ToJSVal(cx, ret, val.GetOriginalString());
}
template<> bool ScriptInterface::FromJSVal<CGUIString>(JSContext* cx, JS::HandleValue v, CGUIString& out)
{
std::wstring val;
if (!ScriptInterface::FromJSVal(cx, v, val))
return false;
out.SetValue(val);
return true;
}
// define some vectors
JSVAL_VECTOR(CVector2D)
JSVAL_VECTOR(std::vector<CVector2D>)
JSVAL_VECTOR(CGUIString)

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2016 Wildfire Games.
/* Copyright (C) 2017 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -284,17 +284,7 @@ bool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Handle
{
CGUIList value;
GUI<CGUIList>::GetSetting(e, propName, value);
JS::RootedObject obj(cx, JS_NewArrayObject(cx, JS::HandleValueArray::empty()));
vp.setObject(*obj);
for (u32 i = 0; i < value.m_Items.size(); ++i)
{
JS::RootedValue val(cx);
ScriptInterface::ToJSVal(cx, &val, value.m_Items[i].GetOriginalString());
JS_SetElement(cx, obj, i, val);
}
ScriptInterface::ToJSVal(cx, vp, value.m_Items);
break;
}
@ -302,28 +292,7 @@ bool JSI_IGUIObject::getProperty(JSContext* cx, JS::HandleObject obj, JS::Handle
{
CGUISeries value;
GUI<CGUISeries>::GetSetting(e, propName, value);
JS::RootedObject obj(cx, JS_NewArrayObject(cx, JS::HandleValueArray::empty()));
vp.setObject(*obj);
for (u32 i = 0; i < value.m_Series.size(); ++i)
{
JS::RootedObject inner_obj(cx, JS_NewArrayObject(cx, JS::HandleValueArray::empty()));
for (u32 j = 0; j < value.m_Series[i].size(); ++j)
{
JS::RootedObject val(cx, JS_NewArrayObject(cx, JS::HandleValueArray::empty()));
JS::RootedValue val_x(cx), val_y(cx);
ScriptInterface::ToJSVal(cx, &val_x, value.m_Series[i][j].X);
ScriptInterface::ToJSVal(cx, &val_y, value.m_Series[i][j].Y);
JS_SetElement(cx, val, 0, val_x);
JS_SetElement(cx, val, 1, val_y);
JS_SetElement(cx, inner_obj, j, val);
}
JS_SetElement(cx, obj, i, inner_obj);
}
ScriptInterface::ToJSVal(cx, vp, value.m_Series);
break;
}
@ -585,98 +554,27 @@ bool JSI_IGUIObject::setProperty(JSContext* cx, JS::HandleObject obj, JS::Handle
case GUIST_CGUIList:
{
u32 length;
if (!vp.isObject() || !JS_GetArrayLength(cx, vpObj, &length))
{
JS_ReportError(cx, "List only accepts a GUIList object");
return false;
}
CGUIList list;
for (u32 i = 0; i < length; ++i)
{
JS::RootedValue element(cx);
if (!JS_GetElement(cx, vpObj, i, &element))
{
JS_ReportError(cx, "Failed to get list element");
return false;
}
std::wstring value;
if (!ScriptInterface::FromJSVal(cx, element, value))
return false;
CGUIString str;
str.SetValue(value);
list.m_Items.push_back(str);
}
if (ScriptInterface::FromJSVal(cx, vp, list.m_Items))
GUI<CGUIList>::SetSetting(e, propName, list);
else
{
JS_ReportError(cx, "Failed to get list '%s'", propName.c_str());
return false;
}
break;
}
case GUIST_CGUISeries:
{
u32 length;
if (!vp.isObject() || !JS_GetArrayLength(cx, vpObj, &length))
{
JS_ReportError(cx, "Table only accepts a GUISeries object");
return false;
}
CGUISeries series;
series.m_Series.resize(length);
for (u32 i = 0; i < length; ++i)
{
JS::RootedValue data_value(cx);
if (!JS_GetElement(cx, vpObj, i, &data_value))
{
JS_ReportError(cx, "Failed to get a data of series");
return false;
}
JS::RootedObject data(cx, data_value.toObjectOrNull());
u32 data_length;
if (!JS_GetArrayLength(cx, data, &data_length))
{
JS_ReportError(cx, "Series only accepts a chart data");
return false;
}
series.m_Series[i].resize(data_length);
for (u32 j = 0; j < data_length; ++j)
{
JS::RootedValue element_value(cx);
if (!JS_GetElement(cx, data, j, &element_value))
{
JS_ReportError(cx, "Failed to get a chart data element");
return false;
}
JS::RootedObject element(cx, element_value.toObjectOrNull());
u32 element_length;
if (!JS_GetArrayLength(cx, element, &element_length) || element_length < 2)
{
JS_ReportError(cx, "Chart data only accepts a point");
return false;
}
JS::RootedValue element_x(cx), element_y(cx);
if (!JS_GetElement(cx, element, 0, &element_x) || !JS_GetElement(cx, element, 1, &element_y))
{
JS_ReportError(cx, "Failed to get a chart point");
return false;
}
if (!ScriptInterface::FromJSVal(cx, element_x, series.m_Series[i][j].X) ||
!ScriptInterface::FromJSVal(cx, element_y, series.m_Series[i][j].Y))
return false;
}
}
if (ScriptInterface::FromJSVal(cx, vp, series.m_Series))
GUI<CGUISeries>::SetSetting(e, propName, series);
else
{
JS_ReportError(cx, "Invalid value for chart series '%s'", propName.c_str());
return false;
}
break;
}

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2016 Wildfire Games.
/* Copyright (C) 2017 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -17,13 +17,12 @@
#include "precompiled.h"
#include "ScriptInterface.h"
#include "ScriptConversions.h"
#include "graphics/Entity.h"
#include "maths/Vector2D.h"
#include "ps/utf16string.h"
#include "ps/CLogger.h"
#include "ps/CStr.h"
#include "scriptinterface/ScriptExtraHeaders.h" // for typed arrays
#define FAIL(msg) STMT(JS_ReportError(cx, msg); return false)
@ -376,71 +375,15 @@ template<> void ScriptInterface::ToJSVal<CStr8>(JSContext* cx, JS::MutableHandle
}
////////////////////////////////////////////////////////////////
// Compound types:
template<typename T> static void ToJSVal_vector(JSContext* cx, JS::MutableHandleValue ret, const std::vector<T>& val)
{
JSAutoRequest rq(cx);
JS::RootedObject obj(cx, JS_NewArrayObject(cx, 0));
if (!obj)
{
ret.setUndefined();
return;
}
for (u32 i = 0; i < val.size(); ++i)
{
JS::RootedValue el(cx);
ScriptInterface::ToJSVal<T>(cx, &el, val[i]);
JS_SetElement(cx, obj, i, el);
}
ret.setObject(*obj);
}
template<typename T> static bool FromJSVal_vector(JSContext* cx, JS::HandleValue v, std::vector<T>& out)
{
JSAutoRequest rq(cx);
JS::RootedObject obj(cx);
if (!v.isObject())
FAIL("Argument must be an array");
obj = &v.toObject();
if (!(JS_IsArrayObject(cx, obj) || JS_IsTypedArrayObject(obj)))
FAIL("Argument must be an array");
u32 length;
if (!JS_GetArrayLength(cx, obj, &length))
FAIL("Failed to get array length");
out.reserve(length);
for (u32 i = 0; i < length; ++i)
{
JS::RootedValue el(cx);
if (!JS_GetElement(cx, obj, i, &el))
FAIL("Failed to read array element");
T el2;
if (!ScriptInterface::FromJSVal<T>(cx, el, el2))
return false;
out.push_back(el2);
}
return true;
}
// Compound types
// Instantiate various vector types:
#define VECTOR(T) \
template<> void ScriptInterface::ToJSVal<std::vector<T> >(JSContext* cx, JS::MutableHandleValue ret, const std::vector<T>& val) \
{ \
ToJSVal_vector(cx, ret, val); \
} \
template<> bool ScriptInterface::FromJSVal<std::vector<T> >(JSContext* cx, JS::HandleValue v, std::vector<T>& out) \
{ \
return FromJSVal_vector(cx, v, out); \
}
VECTOR(int)
VECTOR(u32)
VECTOR(u16)
VECTOR(std::string)
VECTOR(std::wstring)
VECTOR(CStr8)
JSVAL_VECTOR(int)
JSVAL_VECTOR(u32)
JSVAL_VECTOR(u16)
JSVAL_VECTOR(std::string)
JSVAL_VECTOR(std::wstring)
JSVAL_VECTOR(CStr8)
class IComponent;
@ -453,3 +396,25 @@ template<> bool ScriptInterface::FromJSVal<std::vector<Entity> >(JSContext* cx,
{
return FromJSVal_vector(cx, v, out);
}
template<> void ScriptInterface::ToJSVal<CVector2D>(JSContext* cx, JS::MutableHandleValue ret, const CVector2D& val)
{
std::vector<float> vec = {val.X, val.Y};
ToJSVal_vector(cx, ret, vec);
}
template<> bool ScriptInterface::FromJSVal<CVector2D>(JSContext* cx, JS::HandleValue v, CVector2D& out)
{
std::vector<float> vec;
if (!FromJSVal_vector(cx, v, vec))
return false;
if (vec.size() != 2)
return false;
out.X = vec[0];
out.Y = vec[1];
return true;
}

View File

@ -0,0 +1,89 @@
/* Copyright (C) 2017 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. 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.
*
* 0 A.D. 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 0 A.D. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef INCLUDED_SCRIPTCONVERSIONS
#define INCLUDED_SCRIPTCONVERSIONS
#include "ScriptInterface.h"
#include "scriptinterface/ScriptExtraHeaders.h" // for typed arrays
#include <limits>
template<typename T> static void ToJSVal_vector(JSContext* cx, JS::MutableHandleValue ret, const std::vector<T>& val)
{
JSAutoRequest rq(cx);
JS::RootedObject obj(cx, JS_NewArrayObject(cx, 0));
if (!obj)
{
ret.setUndefined();
return;
}
ENSURE(val.size() <= std::numeric_limits<u32>::max());
for (u32 i = 0; i < val.size(); ++i)
{
JS::RootedValue el(cx);
ScriptInterface::ToJSVal<T>(cx, &el, val[i]);
JS_SetElement(cx, obj, i, el);
}
ret.setObject(*obj);
}
#define FAIL(msg) STMT(JS_ReportError(cx, msg); return false)
template<typename T> static bool FromJSVal_vector(JSContext* cx, JS::HandleValue v, std::vector<T>& out)
{
JSAutoRequest rq(cx);
JS::RootedObject obj(cx);
if (!v.isObject())
FAIL("Argument must be an array");
obj = &v.toObject();
if (!(JS_IsArrayObject(cx, obj) || JS_IsTypedArrayObject(obj)))
FAIL("Argument must be an array");
u32 length;
if (!JS_GetArrayLength(cx, obj, &length))
FAIL("Failed to get array length");
out.reserve(length);
for (u32 i = 0; i < length; ++i)
{
JS::RootedValue el(cx);
if (!JS_GetElement(cx, obj, i, &el))
FAIL("Failed to read array element");
T el2;
if (!ScriptInterface::FromJSVal<T>(cx, el, el2))
return false;
out.push_back(el2);
}
return true;
}
#undef FAIL
#define JSVAL_VECTOR(T) \
template<> void ScriptInterface::ToJSVal<std::vector<T> >(JSContext* cx, JS::MutableHandleValue ret, const std::vector<T>& val) \
{ \
ToJSVal_vector(cx, ret, val); \
} \
template<> bool ScriptInterface::FromJSVal<std::vector<T> >(JSContext* cx, JS::HandleValue v, std::vector<T>& out) \
{ \
return FromJSVal_vector(cx, v, out); \
}
#endif //INCLUDED_SCRIPTCONVERSIONS

View File

@ -1,4 +1,4 @@
/* Copyright (C) 2016 Wildfire Games.
/* Copyright (C) 2017 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@ -17,8 +17,7 @@
#include "precompiled.h"
#include "scriptinterface/ScriptInterface.h"
#include "scriptinterface/ScriptExtraHeaders.h" // for typed arrays
#include "scriptinterface/ScriptConversions.h"
#include "maths/Fixed.h"
#include "maths/FixedVector2D.h"
@ -299,21 +298,5 @@ template<> void ScriptInterface::ToJSVal<Grid<u16> >(JSContext* cx, JS::MutableH
ret.setObject(*obj);
}
// TODO: This is copy-pasted from scriptinterface/ScriptConversions.cpp (#define VECTOR stuff), would be nice to remove the duplication
template<> void ScriptInterface::ToJSVal<std::vector<CFixedVector2D> >(JSContext* cx, JS::MutableHandleValue ret, const std::vector<CFixedVector2D>& val)
{
JSAutoRequest rq(cx);
JS::RootedObject obj(cx, JS_NewArrayObject(cx, 0));
if (!obj)
{
ret.setUndefined();
return;
}
for (size_t i = 0; i < val.size(); ++i)
{
JS::RootedValue el(cx);
ScriptInterface::ToJSVal<CFixedVector2D>(cx, &el, val[i]);
JS_SetElement(cx, obj, i, el);
}
ret.setObject(*obj);
}
// define vectors
JSVAL_VECTOR(CFixedVector2D)