Перейти к содержанию

Дайджесты за январь-февраль

Обновления гайдов и аддонов

Январь Февраль

Мониторинг серверов и редактор аддонов

Представляем вам две легенды. То, о чем можно было только мечтать, стало реальностью.

Мониторинг серверов Редактор аддонов

Подсказки из игры на вашем сайте

Теперь вы можете отображать сведения о внутриигровых элементах простым наведением курсора мыши.

Подробнее

Апдейтер аддонов

Представляем вам программу для автообновления аддонов и делимся подробностями.

Подробнее Скачать

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


user02

Рекомендуемые сообщения

Добрый день,

 

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

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

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

 

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

Ссылка на комментарий
Поделиться на другие сайты

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

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

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

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

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

Ссылка на комментарий
Поделиться на другие сайты

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

widget:SetBackgroundColor(ARGB_COLORS[unit.GetClass(targetId).className])

, то будут возникать подобные ошибки. className не определен для некоторых юнитов.

 

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

if unitInfo.className then    
    bar:SetBackgroundColor(classColors[unitInfo.className])
else
    bar:SetBackgroundColor(classColors["UNKNOWN"])
end
Изменено пользователем havendv
Ссылка на комментарий
Поделиться на другие сайты

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

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

 

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

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

:9:

Ссылка на комментарий
Поделиться на другие сайты

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

 

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

Ссылка на комментарий
Поделиться на другие сайты

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

 

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

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

<?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
...

Есть какие-либо еще идеи?

Изменено пользователем user02
Ссылка на комментарий
Поделиться на другие сайты

Нагляднее было бы привести большой кусок кода. По клочкам не увидеть всю картину.

Ссылка на комментарий
Поделиться на другие сайты

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

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" ]
Изменено пользователем havendv
Ссылка на комментарий
Поделиться на другие сайты

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

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
Ссылка на комментарий
Поделиться на другие сайты

 

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

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 } )
Ссылка на комментарий
Поделиться на другие сайты

  • 2 недели спустя...

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

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]

Есть еще какие идеи?

Изменено пользователем user02
Ссылка на комментарий
Поделиться на другие сайты

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Восстановить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...

Важная информация

Пользуясь сайтом, вы принимаете Условия использования