воскресенье, 23 марта 2014 г.

Необходимые плагины для WordPress

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

Akismet - Пожалуй лучший антиспам плагин для WordPress. Имеет бесплатную версию, очень гибок в настройки и почти никогда не пропускает спам! Кстати совсем недавно количество заблокированных комментариев в общем числе превысило 50 миллиардов!

All In One SEO Pack - Полный пакет всего что только нужно по части SEO для WordPress. Бесплатный, функциональный, в общем всё что нужно!

Google XML Sitemaps
- Генерирует карту сайта которая помогает поисковым системам лучше сканировать ваш сайт, абсолютно не заменимая штука (кстати есть альтернатива которая идёт вместе с WP но я ей не пользовался). Так-же плагин полностью бесплатный.

Shortcodes Ultimate - Шорткоды это дар богов! Нет серьёзно, это очень удобная штука! А благодаря данному плагину у вас появляется воистину богатый набор этих самых кодов, так ещё и визуальный интерфейс для их использования в добавок. Полностью бесплатный.

WP Super Cache - Плагин для кеширования контента в WordPress, кеширование нужно для ускорения загрузки сайта. Особенно заметная работа плагина на посещаемых сайтах, где нагрузка достаточно большая. Этот плагин так-же позволяет уменьшить нагрузку на сервер.

Acunetix WP Security
- Какой бы хорошей CMS не был WordPress он всё же уязвим. Этот плагин позволяет повысить безопасность вашего проекта, достаточно лёгок в обращение, но новичку может показаться слишком сложным.

Вот мой список плагинов :)
Если у вас тоже есть что-то что вы стараетесь брать с собой, пишите в комментариях!

понедельник, 17 февраля 2014 г.

Как я ASP.Net с JustClick подружил.

 Введение

Что такое JustClick?

"херня забагованая" (с) тим-лид
JustClick - Это такая платформа для инфобизнесменов,  соль в том что там всё автоматизировано, повсюду цветастые кнопки на которых написано "сделать красиво".

Но к сожалению не всё так радужно. И вот мы - кучка программистов уже делаем свою SaaS, с шахматами и балеринами, но для начало нам нужно было плавно переводить все ресурсы. После того как была написана основа мы приступили к интеграции, а именно к покупки товаров. Соль в том что бы при покупки в JustClick, товар был бы доступен и в личном кабинете на нашей платформе, собственно кусок из моих похождений я постараюсь описать в данной записи.

Это не мы такие, это реквест такой

Мне очень понравилось что в JustClick было API и мне очень не понравилось какое у них API. Самый логичное решение сделать обмен через скажем JSON или хотя бы XML. Но нет, ребята решили что PHP у всех и нужно пользоваться чем-то сильно зависимым от подобных языков.

Но нам ли жаловаться. 

Для начала нужно проделать такой финт конём (сразу скажу что с Asp.Net слабо знаком так-что быдлокодер костылём велосипед подгоняет) 
-Берём и копируем отседова секретный ключ подписи "Мой магазин" - "Магазин" - "Настройки" - "RussianPostService и API" 
-Создаём новую веб форму.
-Идём в товар, ставим в настройках API в графе оповещения ссылку на нашу форму.
-В форме ловим пост запрос который выглядит так в PHP и отправляется через urlencode(!):
 
array(
'id' => номер заказа
'first_name' => имя клиента
'last_name' => фамилия клиента
'middle_name' => отчество клиента
'email' => мейл клиента
'phone' => телефон клиента
'city' => город доставки
'country' => страна доставки
'address' => адрес доставки
'region' => регион доставки
'postalcode' => почтовый индекс
'created' => время создания заказа
'paid' => время оплаты заказа
'items' => array( массив товаров
array(
'id' => символьный идентификатор
'title' => название товара
'sum' => стоимость товара
),
array(
'id' => символьный идентификатор
'title' => название товара
'sum' => стоимость товара
),
...
)
'hash' => md5(номер заказа + мейл клиента + дата оплаты + секретный ключ)
)

 
До нас доходит примерно следующее

 id=3224966&first_name=asf&
last_name=&middle_name=&email=*******&phone=&city=&country=RUS&address=sdf&region=&postalcode=&created=1392641297&paid=1392641312&items[0][id]=ebook&items[0][title]=??????????? ?????&items[0][sum]=500.00&items[1][id]=0&hash=*********&


ASP.net своими силами пытается разбросать это всё по коллекции типа NameValueCollection
и скажу даже больше, у него это получается! Ну как получается....
Допустим мы можем взять из Request все не вложенные элементы.

 
 
Requeste["id"]; //norm
Requeste["email"]; //norm
Requeste["items"]; //EMPTY!!!

А фишка в том, что все вложенные элементы не парсятся до ещё одного набор коллекций. Нет. Оно превращается в ключи... Выгляди это примерно так:

 
Requeste["items[0][sum"]; //norm
Requeste["items[2][sum"]; //norm

Работать как все понимают с этим трудно, и даже слегка больно.

Заключение

Все пидорасы один я дартаньян (c)

Либо я не секу фишку, либо ребятам из JustClick стоило сделать лучше. Но в любом случае надеюсь эта заметка кому нибудь пригодится. 

пятница, 24 января 2014 г.

VisualWebSiteOptimizer баг с вариантами.

Признаюсь сразу что это не совсем баг а всего лишь кривая вёрстка команды заказчика
Подолгу службы мне иногда приходится общаться с клиентами моей фирмы, недавно к нам обратился человек у которого варианты лэндинга не работали на продакшене и не были видны в превью. Это не приятная ситуация и мне поручили с ней разобраться. Первым делом я обратился в саппорт, мне ответили следующее:

Thank you for contacting us. I have checked the test and would like to tell you that there is an iframe element when the webpage is loaded in the VWO editor which is causing the CSS selector path to be different when the visitor lands on the webpage directly and hence VWO is not able to find the element and apply the changes (please check the screenshot 1 attached). 

So I would recommend that you either insert an ID on the DIV element after the opening body tag so that the CSS selector path is calculated from that element or you can create an MVT test and add the CSS selector path (font.actiontitle>center) manually (as shown in the screenshot2) and then disable all the variations except for the control and the last variation in the test.
  Я как нормальный человек понял мало. Но взглянул на лэндинг которые сверстали фрилансеры, я впал в не большую фрустрацию с большим желанием выпить ещё одну чашку кофе. Дело в том, что на КАЖДЫЙ тег приходился свой собственный id, самое забавное что это не генерированная странница а свёрстанная вполне реальным человеком с вполне функциональными руками (ну по крайней мере в ухе ими поковыряться можно). Из-за такой "пёрстости" страницы, ломались селекторы. Проблема решалась заклчением всей страницы в див с id = VWOWrapper, под всей страницей я имею ввиду конечно-же всё от ‹ body › и до ‹ /body › .
Надеюсь Вам это помогло!

Кастомизация Unity Web Player [Preloader]


четверг, 9 января 2014 г.

Хостинг Unity Web Player

Написал основу за выходные, сейчас тружусь над улучшением сервиса :) 

Хостинг Unity Web Player

Пишем Dissolve Shader [Хабра]

Введение

Перед новым годом, я решил попробовать себя в написании шейдеров. В качестве цели я избрал для себя шейдер растворяющегося объекта, 31 декабря я его успешно закончил и теперь пришло время что-то с ним делать. На ассет сторе сказали что всё отлично но уже парочка похожих есть, по этому я постараюсь разобрать его в этой статье. В итоге у нас должно получиться вот это:

  Путей реализации есть несколько:
  • Alpha
  • CutOff
  • Grab Texture
В итоге у нас получится 3 шейдера, 2 использующие только альфу и которые могут взлететь на моб. девайсах и один с AlphaTest который выглядит посимпатичней но более прожорливый. Благодаря AlphaTest мы можем отключить отсечение невидимых полигонов и не получать наслоение. Но заплатить придётся шейдерной моделью 2.0 и использовать 3.0 из-за чего нельзя будет использовать на моб. девайсах.

Каркас

Общий алгоритм примерно такой:
  • Берём яркость пикселя с маски разрушения или прямо с главной текстуры
  • Сравниваем эту яркость с N
  • Если яркость больше N то альфу пикселя ставим в нолик
В итоге получится не так красиво как на первом видео.
Нам не хватает карт нормалей, и самого крутого. Линий! Алгоритм инлайнов у меня такой:
  • Берём яркость пикселя с маски разрушения, но с оффсетом по UV + LineSize. И ещё один но оффсет уже UV - LineSize
  • Если хотя бы один из пикселей меньше N, то мы устанавливаем цвет пикселя из текстуры для линий
  • Иначе ставим альфу в ноль (Это как замена аналогичной операции в первом алгоритме)
Резюмирую выше сказанное, мы получаем отсечение по маске и если пиксели отсекаем то проверяем нету ли впритык к нему не отсечённые, если они есть мы становимся краем и ставим себе определённый цвет.

Ближе к телу коду

Если прибавить ко всему выше сказанному наложение нормалек и смещение текстуры линии ещё по синусоидальному времени, получится вот такое вот полотно.
 Shader "HolyMonkey/Dissolve/Bumped" {

 Properties {
     _MainColor ("Main Color", Color) = (1,1,1,1)
  _MainTex ("Base (RGB)", 2D) = "white" {}
  _Mask("Mask To Dissolve", 2D) = "white" {}
  _LineTexture("Line Texture", 2D) = "white" {}
  _Range ("Range", Range(0,3)) = 0
  _LineSize ("LineSize", Float) = 0.001
  _Color ("Line Color", Color) = (1,1,1,1)
  _BumpMap ("Normalmap", 2D) = "bump" {}
  _Cutoff ("Alpha cutoff", Range(0,1)) = 0.5
 }
 
 SubShader {
  Tags {"Queue"="AlphaTest" "IgnoreProjector"="True" "RenderType"="TransparentCutout"}
  LOD 300
  ZWrite On
  Cull Off
  CGPROGRAM 
  #pragma target 3.0
  #include "UnityCG.cginc"
  #pragma surface surf Lambert alphatest:_Cutoff
        

  sampler2D _MainTex;
  sampler2D _LineTexture;
  sampler2D _BumpMap;
  sampler2D _Mask;
  half4 _Color;
  half4 _MainColor;
  float _Range;
  float _LineSize;
             
  struct Input {
   float2 uv_MainTex;
   float2 uv_BumpMap;
                        float2 uv_Detail;
  };
            
  void surf (Input IN, inout SurfaceOutput o) {
   half4 c = tex2D (_MainTex, IN.uv_MainTex);
   half4 m = tex2D (_Mask, IN.uv_MainTex);
          half4 lc =  tex2D (_Mask, IN.uv_MainTex - _LineSize);
          half4 lc2 = tex2D (_Mask, IN.uv_MainTex + _LineSize);
   half4 lc3 = tex2D(_LineTexture, IN.uv_MainTex + _SinTime) * _Color;    
    
          o.Albedo = c *  _MainColor;
          o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
          o.Alpha = 1;
      
   float factor = m.rgb.x + m.rgb.y + m.rgb.z;
   if(factor >= _Range)
   {
      float factor2 = lc.rgb.x + lc.rgb.y + lc.rgb.z;
      float factor3 = lc2.rgb.x + lc2.rgb.y + lc2.rgb.z;
      if(factor2 < _Range || factor3 < _Range)
      {
         o.Albedo = lc3;
      }
      else
      {
                  o.Alpha = 0.0;
               }
            }
  }
  ENDCG
 } 
 Fallback "Diffuse"
}
Ещё можно поиграться с не которыми аспектами и получить следующее
Shader "HolyMonkey/Dissolve/Culling-Mobile" {

 Properties {
     _MainColor ("Main Color", Color) = (1,1,1,1)
  _MainTex ("Base (RGB)", 2D) = "white" {}
  _Mask("Mask To Dissolve", 2D) = "white" {}
  _LineTexture("Line Texture", 2D) = "white" {}
  _Range ("Range", Range(0,3)) = 0
  _LineSize ("LineSize", Float) = 0.001
  _Color ("Line Color", Color) = (1,1,1,1)
  _BumpMap ("Normalmap", 2D) = "bump" {}
 }
 
 SubShader {
  Tags {"Queue"="Transparent" "IgnoreProjector"="True" "RenderType"="Transparent"}
  LOD 300
  CGPROGRAM 
  #pragma target 2.0
  #include "UnityCG.cginc"
  #pragma surface surf Lambert alpha 
        

  sampler2D _MainTex;
  sampler2D _LineTexture;
  sampler2D _BumpMap;
  sampler2D _Mask;
  half4 _Color;
  half4 _MainColor;
  float _Range;
  float _LineSize;
             
  struct Input {
   float2 uv_MainTex;
   float2 uv_BumpMap;
            float2 uv_Detail;
  };
            
  void surf (Input IN, inout SurfaceOutput o) {
   half4 c = tex2D (_MainTex, IN.uv_MainTex);
   half4 m = tex2D (_Mask, IN.uv_MainTex);
      half4 lc =  tex2D (_Mask, IN.uv_MainTex - _LineSize);
      half4 lc2 = tex2D (_Mask, IN.uv_MainTex + _LineSize);
   half4 lc3 = tex2D(_LineTexture, IN.uv_MainTex + _SinTime) * _Color;    
    
      o.Albedo = c *  _MainColor;
      o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
      o.Alpha = 1;
      
   float factor = m.rgb.x + m.rgb.y + m.rgb.z;
   if(factor >= _Range)
   {
      float factor2 = lc.rgb.x + lc.rgb.y + lc.rgb.z;
      float factor3 = lc2.rgb.x + lc2.rgb.y + lc2.rgb.z;
      if(factor2 < _Range || factor3 < _Range)
      {
         o.Albedo = lc3;
      }
      else
      {
                  o.Alpha = 0.0;
               }
            }
  }
  ENDCG
 } 
 Fallback "Diffuse"
}
Shader "HolyMonkey/Dissolve/NotTransparent" {

 Properties {
     _MainColor ("Main Color", Color) = (1,1,1,1)
  _MainTex ("Base (RGB)", 2D) = "white" {}
  _BackTexture ("Back Texture", 2D) = "white" {}
  _Mask("Mask To Dissolve", 2D) = "white" {}
  _LineTexture("Line Texture", 2D) = "white" {}
  _Range ("Range", Range(0,3)) = 0
  _LineSize ("LineSize", Float) = 0.001
  _Color ("Line Color", Color) = (1,1,1,1)
  _BumpMap ("Normalmap", 2D) = "bump" {}
 }
 
 SubShader {
  LOD 300
  ZWrite On
  Cull Off
  
  CGPROGRAM 
  #pragma target 2.0
  #include "UnityCG.cginc"
  #pragma surface surf Lambert
        

  sampler2D _MainTex;
  sampler2D _LineTexture;
  sampler2D _BumpMap;
  sampler2D _Mask;
  sampler2D _BackTexture;
  half4 _Color;
  half4 _MainColor;
  float _Range;
  float _LineSize;
             
  struct Input {
   float2 uv_MainTex;
   float2 uv_BumpMap;
            float2 uv_Detail;
  };
            
  void surf (Input IN, inout SurfaceOutput o) {
   half4 c = tex2D (_MainTex, IN.uv_MainTex);
   half4 m = tex2D (_Mask, IN.uv_MainTex);
      half4 lc =  tex2D (_Mask, IN.uv_MainTex - _LineSize);
      half4 lc2 = tex2D (_Mask, IN.uv_MainTex + _LineSize);
   half4 lc3 = tex2D(_LineTexture, IN.uv_MainTex + _SinTime) * _Color;    
   half4 bc  = tex2D(_BackTexture, IN.uv_MainTex);
      o.Albedo = c *  _MainColor;
      o.Normal = UnpackNormal(tex2D(_BumpMap, IN.uv_BumpMap));
      
   float factor = m.rgb.x + m.rgb.y + m.rgb.z;
   if(factor >= _Range)
   {
      float factor2 = lc.rgb.x + lc.rgb.y + lc.rgb.z;
      float factor3 = lc2.rgb.x + lc2.rgb.y + lc2.rgb.z;
      if(factor2 < _Range || factor3 < _Range)
      {
         o.Albedo = lc3;
      }
      else
      {
         o.Albedo = bc;
         o.Normal = float3(1,1,1);
      }
            }
  }
  ENDCG
 } 
 Fallback "Diffuse"
}

Заключение

Написать получилось мало, но думаю дедуктивный код это искупает. Там используются простые вещи, и на хабре есть статьи с их ним разбором. Исходники со всеми нужными ресурсами Вы можете скачать из репозитория на GitHub

четверг, 26 декабря 2013 г.

My Dissolve Shader for Unity3D

Эх, помню три года назад когда только начинал путь в программирование и разработку игр, увидел демонстрацию такого же шейдера. Он меня привёл в поросячий восторг, и я считал что чтобы сделать его, нужно быть гуру. Но оказалось всё на много проще, сидел, делать нечего, вспомнил про эту штуку, сделал за 10 минут :c

Первый вариант


      Второй вариант