Jump to content
Alloder.pro  about Allods with love 😱
Search In
  • More options...
Find results that contain...
Find results in...

Servers monitoring and the Addons Editor

We present you two legends. All dreams come true.

Servers monitoring The Addons Editor

Digest April

We talk about what was done and updated in the past month. We help keep abreast of events.

Read more

Game tooltips

Tooltips provide a way for 3rd party fansites and extensions to display detailed information on mouseover.

Read more

Периодическая ошибка при задании фона виджита


user02
 Share

Recommended Posts

Добрый день,

 

столкнулся в своем аддоне со следующей периодической ошибкой при задании цвета в виджете:

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 }
})

Соответственно, хотелось понять с чем это могло быть связано и может ли быть это из-за частого задания цвета или еще каких ограничений? Например асинхронного задания цвета?!

 

Заранее спасибо.

Link to comment
Share on other sites

При этом иногда ошибка возникает, а иногда нет.

Она возникает бессистемно или только на определенных виджетах?

Как правило эта ошибка говорит о том, что у виджета нету слоя заднего фона.

Надо проверить соответствующий *.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) тоже отсутствует :)

Посему всякие блокировки, семафоры, мутексы, критические секции и прочую синхронизацию - (в данном случае) в помойку. :)

Link to comment
Share on other sites

Если задаете цвет строкой вида 

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 by havendv
Link to comment
Share on other sites

У себя просто сделал так 

if unitInfo.className then    
    bar:SetBackgroundColor(classColors[unitInfo.className])
else
    bar:SetBackgroundColor(classColors["UNKNOWN"])
end

 

Короче было бы вот так:

bar:SetBackgroundColor(classColors[unitInfo.className or "UNKNOWN"])

:9:

Link to comment
Share on other sites

К тому же аддоны не реентерабельны, т.е. не может такого быть, чтобы две функции одного аддона выполнялись параллельно. Вытеснение (preemption) тоже отсутствует  :)

 

Что-то я не помню, чтоб coroutine выпилили, если автор аддона жаждет многопоточности, он ее получит.

Link to comment
Share on other sites

Опишу более подробней.

 

Использование:

при появлении юнита создается виджит на базе шаблона:

<?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 by user02
Link to comment
Share on other sites

Ну, опять же, повторюсь 

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 by havendv
Link to comment
Share on other sites

Развернуто можно описать вот так код:

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
Link to comment
Share on other sites

 

Ну, опять же, повторюсь 

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 } )
Link to comment
Share on other sites

  • 2 weeks later...

И все же ошибка сного появилась даже при явном заданиии.

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 by user02
Link to comment
Share on other sites

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

 Share

×
×
  • Create New...

Important Information

By using our site you agree to the Terms of Use