user02 Posted November 12, 2014 Share Posted November 12, 2014 Добрый день, столкнулся в своем аддоне со следующей периодической ошибкой при задании цвета в виджете: Error: addon UData: Widgets::LuaSetBackgroundColor: Can't set background color, details: int __cdecl Widgets::LuaSetBackgroundColor(struct lua_State *) Error: addon UData: Error: addon UData: Error: addon UData: func: SetBackgroundColor, method, line: -1, defined: C, line: -1, [C] При этом иногда ошибка возникает, а иногда нет.функции передается стандартный массив в формате {a, r, g, b}: Global( "ARGB_COLORS", { [ "BARD" ] = { a = 1, r = 106/255, g = 230/255, b = 223/255 } , [ "DRUID" ] = { a = 1, r = 255/255, g = 118/255, b = 60/255 } , [ "ENGINEER" ] = { a = 1, r = 135/255, g = 163/255, b = 177/255 } , [ "MAGE" ] = { a = 1, r = 126/255, g = 159/255, b = 255/255 } , [ "NECROMANCER" ] = { a = 1, r = 208/255, g = 69/255, b = 75/255 } , [ "PALADIN" ] = { a = 1, r = 207/255, g = 220/255, b = 155/255 } , [ "PRIEST" ] = { a = 1, r = 255/255, g = 207/255, b = 123/255 } , [ "PSIONIC" ] = { a = 1, r = 221/255, g = 123/255, b = 245/255 } , [ "STALKER" ] = { a = 1, r = 150/255, g = 204/255, b = 86/255 } , [ "WARRIOR" ] = { a = 1, r = 143/255, g = 119/255, b = 75/255 } , [ "MOB" ] = { a = 1, r = 255/255, g = 0/255, b = 0/255 } , [ "UNDEFINED" ] = { a = 1, r = 0/255, g = 255/255, b = 0/255 } , [ "MOUNT" ] = { a = 1, r = 0.1, g = 1, b = 0.1 } , [ "DISABLE" ] = { a = 1, r = 0, g = 0, b = 0 } }) Соответственно, хотелось понять с чем это могло быть связано и может ли быть это из-за частого задания цвета или еще каких ограничений? Например асинхронного задания цвета?! Заранее спасибо. Quote Link to comment Share on other sites More sharing options...
hal.dll Posted November 12, 2014 Share Posted November 12, 2014 При этом иногда ошибка возникает, а иногда нет. Она возникает бессистемно или только на определенных виджетах? Как правило эта ошибка говорит о том, что у виджета нету слоя заднего фона. Надо проверить соответствующий *.xdb на предмет наличия тега: <BackLayer href="TransparentLayer.(WidgetLayerSimpleTexture).xdb#xpointer(/WidgetLayerSimpleTexture)" /> Если пустой, значит надо задать его. Пример файла прозрачного слоя TransparentLayer.(WidgetLayerSimpleTexture).xdb: <?xml version="1.0" encoding="UTF-8" ?> <WidgetLayerSimpleTexture> <Color>0x00000000</Color> <Grayed>false</Grayed> <BlendEffect>BLEND_EFFECT_ALPHABLND</BlendEffect> <flatPlacement>false</flatPlacement> <lazyLoad>false</lazyLoad> <textureItem href="" /> <Scaling>true</Scaling> </WidgetLayerSimpleTexture> SetBackgroundColor залёт его нужным цветов и он станет непрозрачным. может ли быть это из-за частого задания цвета или еще каких ограничений? Вероятность этого крайне низка. Например асинхронного задания цвета?! Аналогично. К тому же аддоны не реентерабельны, т.е. не может такого быть, чтобы две функции одного аддона выполнялись параллельно. Вытеснение (preemption) тоже отсутствует Посему всякие блокировки, семафоры, мутексы, критические секции и прочую синхронизацию - (в данном случае) в помойку. Quote Link to comment Share on other sites More sharing options...
havendv Posted November 13, 2014 Share Posted November 13, 2014 (edited) Если задаете цвет строкой вида widget:SetBackgroundColor(ARGB_COLORS[unit.GetClass(targetId).className]) , то будут возникать подобные ошибки. className не определен для некоторых юнитов. У себя просто сделал так if unitInfo.className then bar:SetBackgroundColor(classColors[unitInfo.className]) else bar:SetBackgroundColor(classColors["UNKNOWN"]) end Edited November 13, 2014 by havendv Quote Link to comment Share on other sites More sharing options...
Altair Posted November 13, 2014 Share Posted November 13, 2014 У себя просто сделал так if unitInfo.className then bar:SetBackgroundColor(classColors[unitInfo.className]) else bar:SetBackgroundColor(classColors["UNKNOWN"]) end Короче было бы вот так: bar:SetBackgroundColor(classColors[unitInfo.className or "UNKNOWN"]) Quote Link to comment Share on other sites More sharing options...
havendv Posted November 13, 2014 Share Posted November 13, 2014 Угу. Логика здорово сокращает код, но не так наглядна. Quote Link to comment Share on other sites More sharing options...
xxxgoes Posted November 13, 2014 Share Posted November 13, 2014 К тому же аддоны не реентерабельны, т.е. не может такого быть, чтобы две функции одного аддона выполнялись параллельно. Вытеснение (preemption) тоже отсутствует Что-то я не помню, чтоб coroutine выпилили, если автор аддона жаждет многопоточности, он ее получит. Quote Link to comment Share on other sites More sharing options...
user02 Posted November 13, 2014 Author Share Posted November 13, 2014 (edited) Опишу более подробней. Использование: при появлении юнита создается виджит на базе шаблона: <?xml version="1.0" encoding="UTF-8" ?> <WidgetPanel> <Name>UBar</Name> <Priority>2</Priority> <BackLayer href="UBar.(WidgetLayerSimpleTexture).xdb#xpointer(/WidgetLayerSimpleTexture)" /> <Placement> <X> <Align>WIDGET_ALIGN_LOW</Align> <Pos>20</Pos> <Size>100</Size> </X> <Y> <Align>WIDGET_ALIGN_LOW</Align> <Pos>0</Pos> <Size>20</Size> </Y> </Placement> <TransparentInput>true</TransparentInput> </WidgetPanel> UBar.(WidgetLayerSimpleTexture).xdb#xpointer(/WidgetLayerSimpleTexture) <?xml version="1.0" encoding="UTF-8" ?> <WidgetLayerSimpleTexture> <Color>0xffffffff</Color> <Grayed>false</Grayed> <BlendEffect>BLEND_EFFECT_ALPHABLND</BlendEffect> <flatPlacement>false</flatPlacement> <lazyLoad>false</lazyLoad> <textureItem href="UBar.(UITextureElement).xdb#xpointer(/UITextureElement)" /> <textureMask href="" /> <Scaling>true</Scaling> </WidgetLayerSimpleTexture> ... При появлении (EVENT_UNIT_SPAWNED) юнита идет поиск объекта и если есть такой идет обновление цвета: if color then UBar:SetBackgroundColor( color ) end Цвет определяется в зависимости от типа юнита: color = if unit.IsPlayer( unit_id ) then ARGB_COLORS[ unit.GetClass( unit_id ).className ] else ARGB_COLORS[ "MOB" ] end Ошибка случается в одном и том же типе виджитов. Случается это не всегда. Вставлял перед изменением вывод в файл LogInfo( class_name). Иногда после класса есть ошибка, иногда нет, т.е. PALADIN BARD PALADIN Error... MOB STALKER ... Есть какие-либо еще идеи? Edited November 13, 2014 by user02 Quote Link to comment Share on other sites More sharing options...
LEM Posted November 13, 2014 Share Posted November 13, 2014 Нагляднее было бы привести большой кусок кода. По клочкам не увидеть всю картину. Quote Link to comment Share on other sites More sharing options...
havendv Posted November 13, 2014 Share Posted November 13, 2014 (edited) Ну, опять же, повторюсь unit.GetClass( unit_id ) может иметь значение nil. Учитывайте это, ибо в таких случаях ваш код и дает ошибку. function GetClass( unitId )-- возвращаемые значения - таблица с параметрами класса или nil, если данные недоступны Просто добавьте проверку local classInfo=unit.GetClass(unit_id) color = ARGB_COLORS[ classInfo and classInfo.className or not unit.IsPlayer( unit_id ) and "MOB" or "UNDEFINED" ] Edited November 13, 2014 by havendv Quote Link to comment Share on other sites More sharing options...
user02 Posted November 13, 2014 Author Share Posted November 13, 2014 Развернуто можно описать вот так код: local CLASSES = { [ 'BARD' ] = 'BARD' ... , [ 'MOB' ] = 'MOB' , [ 'UNDEFINED' ] = 'UNDEFINED' } local ARGB_COLORS = { [ "BARD" ] = { a = 1, r = 106/255, g = 230/255, b = 223/255 } , [ "DRUID" ] = { a = 1, r = 255/255, g = 118/255, b = 60/255 } , [ "ENGINEER" ] = { a = 1, r = 135/255, g = 163/255, b = 177/255 } , [ "MAGE" ] = { a = 1, r = 126/255, g = 159/255, b = 255/255 } ... } onEvent["EVENT_UNIT_SPAWNED"] = function( params ) local unit_id = params.unitId local uBar = self.GetUBar( unit_id ) -- ищет нужный виджет в наборе существующих виджетов (либо по имени юнита, либо по id юнита) if uBar then local class_name = unit.IsPlayer( unit_id ) and unit.GetClass( unit_id ).className or 'MOB' class_name = CLASSES[ class_name ] or 'UNDEFINED' local info = object.GetHealthInfo( unit_id ) local hp = ( info and info.valuePercents or 0 ) local pos = uBar:GetPlacementPlain() pos.sizeX = hp uBar:SetPlacementPlain( pos ) LogInfo( class_name ) local color = ARGB_COLORS[ class_name ] if color then uBar:SetBackgroundColor( color ) end else AddUBar( unit_id ) -- инициализируется новый виджет UBAR:Init( unit_id ), добавляется в массив uBars[ unit_id ] и отображается на экране end end Quote Link to comment Share on other sites More sharing options...
user02 Posted November 13, 2014 Author Share Posted November 13, 2014 Ну, опять же, повторюсь unit.GetClass( unit_id ) может иметь значение nil. Учитывайте это, ибо в таких случаях ваш код и дает ошибку. function GetClass( unitId )-- возвращаемые значения - таблица с параметрами класса или nil, если данные недоступны Просто добавьте проверку local classInfo=unit.GetClass(unit_id) color = ARGB_COLORS[ classInfo and classInfo.className or not unit.IsPlayer( unit_id ) and "MOB" or "UNDEFINED" ] попробую явно прописать цвет, посмотрю будет ли выдаваться ошибка, т.е. uBar:SetBackgroundColor( { a = 1, r = 126/255, g = 159/255, b = 255/255 } ) Quote Link to comment Share on other sites More sharing options...
user02 Posted November 23, 2014 Author Share Posted November 23, 2014 (edited) И все же ошибка сного появилась даже при явном заданиии. Global( "ARGB_COLORS", { [ "BARD" ] = { a = 1, r = 106/255, g = 230/255, b = 223/255 } , [ "DRUID" ] = { a = 1, r = 255/255, g = 118/255, b = 60/255 } , [ "ENGINEER" ] = { a = 1, r = 135/255, g = 163/255, b = 177/255 } , [ "MAGE" ] = { a = 1, r = 126/255, g = 159/255, b = 255/255 } , [ "NECROMANCER" ] = { a = 1, r = 208/255, g = 69/255, b = 75/255 } , [ "PALADIN" ] = { a = 1, r = 207/255, g = 220/255, b = 155/255 } , [ "PRIEST" ] = { a = 1, r = 255/255, g = 207/255, b = 123/255 } , [ "PSIONIC" ] = { a = 1, r = 221/255, g = 123/255, b = 245/255 } , [ "STALKER" ] = { a = 1, r = 150/255, g = 204/255, b = 86/255 } , [ "WARRIOR" ] = { a = 1, r = 143/255, g = 119/255, b = 75/255 } , [ "MOB" ] = { a = 1, r = 255/255, g = 0/255, b = 0/255 } , [ "UNDEFINED" ] = { a = 1, r = 0/255, g = 255/255, b = 0/255 } , [ "DISABLE" ] = { a = 1, r = 0, g = 0, b = 0 } , [ "MOUNT" ] = { a = 1, r = 0.1, g = 1, b = 0.1 } }) uBar:SetBackgroundColor( ARGB_COLORS[ "MOUNT" ] ) Error: addon UData: Widgets::LuaSetBackgroundColor: Can't set background color, details: int __cdecl Widgets::LuaSetBackgroundColor(struct lua_State *) Error: addon UData: func: SetBackgroundColor, method, line: -1, defined: C, line: -1, [C] Есть еще какие идеи? Edited November 23, 2014 by user02 Quote Link to comment Share on other sites More sharing options...
Recommended Posts