<?xml version="1.0" encoding="UTF-8" standalone="no"?><?xml-stylesheet href="http://www.blogger.com/styles/atom.css" type="text/css"?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:blogger="http://schemas.google.com/blogger/2008" xmlns:gd="http://schemas.google.com/g/2005" xmlns:georss="http://www.georss.org/georss" xmlns:openSearch="http://a9.com/-/spec/opensearchrss/1.0/" xmlns:thr="http://purl.org/syndication/thread/1.0"><id>tag:blogger.com,1999:blog-1506668875974051482</id><updated>2026-10-13T17:52:59.238-07:00</updated><category term="Software"/><category term="Others"/><category term="technology"/><category term="Blender"/><category term="chatbot"/><category term="design"/><category term="it-tude"/><category term="python"/><category term="Android"/><category term="designs"/><category term="Artificial Intelligence"/><category term="it-tude.com"/><category term="Web"/><category term="e-patrol"/><category term="Ai"/><category term="Javascript"/><category term="Microsoft"/><category term="OS"/><category term="animasi"/><category term="blog"/><category term="machine learning"/><category term="tutorial"/><category term="windows 8"/><category term="Emulator"/><category term="Local Area Network"/><category term="Website"/><category term="photoshop"/><category term="tutorial web"/><category term="windows 7"/><category term="wordpress"/><category term="3D"/><category term="Blender Material"/><category term="Database"/><category term="Google"/><category term="Illustrator"/><category term="Mac"/><category term="applikasi"/><category term="belajar membuat web"/><category term="benefits"/><category term="command"/><category term="computer graphics"/><category term="game"/><category term="hardware"/><category term="how to"/><category term="jaringan"/><category term="lead-capture"/><category term="overview"/><category term="pc tweak"/><category term="penjelasan content"/><category term="template"/><category term="tools web"/><category term="umkm"/><category term="umum"/><category term="virus"/><category term="web tools"/><category term="winsock"/><category term="workflow"/><category term="4G"/><category term="A3"/><category term="A4"/><category term="A4 ukuran"/><category term="Akun Email Windows"/><category term="Alcohol 52%"/><category term="Apple"/><category term="Artikel"/><category term="CG 3D"/><category term="Change Account"/><category term="ChatGPT"/><category term="Cognitive Computing"/><category term="Computer for Dummy"/><category term="Content"/><category term="Corel"/><category term="Dasar"/><category term="Data Refresh"/><category term="Digital"/><category term="Dingin tanpa Kulkas"/><category term="Download"/><category term="Email Account"/><category term="Facebook"/><category term="Font"/><category term="Free"/><category term="G-suit"/><category term="HArdisk"/><category term="IT-Tude Notes"/><category term="Indonesia"/><category term="Inside Computer"/><category term="Intel"/><category term="Interactive"/><category term="Istilah"/><category term="Javascript dasar"/><category term="Kartu Grafis"/><category term="Kotlin"/><category term="Kulkas tanpa listrik"/><category term="LAN Koneksi Nirkabel"/><category term="Lan Messenger"/><category term="MX Record"/><category term="Macintosh"/><category term="Memory System"/><category term="Mobile App"/><category term="Monitor"/><category term="Naruto"/><category term="Net : err_cert_date_invalid"/><category term="Neural Network"/><category term="Online"/><category term="PHP"/><category term="Panduan"/><category term="Port USB"/><category term="Postgre"/><category term="PostreSql"/><category term="Processor"/><category term="Psikologi"/><category term="Quotes"/><category term="Ram"/><category term="SIM elektronik"/><category term="Session Management"/><category term="Steve Jobs"/><category term="Teks bergerak"/><category term="Ukuran kertas"/><category term="WP"/><category term="Windows"/><category term="Wireless"/><category term="android pasword"/><category term="apa copyrigth"/><category term="apa postgre"/><category term="art"/><category term="ascii how"/><category term="ascii used"/><category term="avatars"/><category term="belajar python"/><category term="benchmark"/><category term="bikin sim"/><category term="bikin sim cepat"/><category term="blender Script"/><category term="booting"/><category term="browser"/><category term="browser canggih"/><category term="browser error"/><category term="buat sim"/><category term="buat web"/><category term="cannot open https"/><category term="cara buka password"/><category term="cepat"/><category term="chatbot-it-tude"/><category term="cheatsheet python"/><category term="chrome offline game"/><category term="code wilayah gsm"/><category term="compleate"/><category term="cool without refrigerator"/><category term="css"/><category term="daftar kode bank"/><category term="daftar nomor hp"/><category term="danger"/><category term="danger of selfi"/><category term="dasar css"/><category term="developer"/><category term="driver solution"/><category term="e-patrol cara login"/><category term="email"/><category term="email windows 8"/><category term="episode"/><category term="external drive"/><category term="facebook error"/><category term="fb"/><category term="fb error"/><category term="footage"/><category term="founder"/><category term="framework"/><category term="free driver"/><category term="game gratis"/><category term="glossary"/><category term="gong"/><category term="graphics"/><category term="how ascii"/><category term="html"/><category term="https"/><category term="https error"/><category term="https error - browser error err_cert_date_invalid"/><category term="ip windows 7"/><category term="javascript dan jquery"/><category term="joomla"/><category term="jquery"/><category term="jquery contoh"/><category term="kertas"/><category term="kode transfer antar bank"/><category term="komputer"/><category term="komputer grafika"/><category term="kulkas bio"/><category term="laravel"/><category term="layanan it-tude."/><category term="lengkap javascript"/><category term="lnk folder"/><category term="lost folder"/><category term="lupa password"/><category term="lupa pasword"/><category term="mac hardware"/><category term="maksud warna"/><category term="manga"/><category term="mengenali nomor hp"/><category term="mengirim pesan gratis"/><category term="microsoft azure"/><category term="modem usb"/><category term="most used ascii"/><category term="multi screen"/><category term="multi screen apps"/><category term="netshell utllity"/><category term="nomor gsm"/><category term="nomor hp"/><category term="operator"/><category term="oprek"/><category term="oxygenOS"/><category term="panduan pemula"/><category term="password android lupa"/><category term="pengertian css"/><category term="penjelasan custom blog header"/><category term="pip"/><category term="prestashop"/><category term="produk prestashop"/><category term="programming"/><category term="psikologi warna"/><category term="repair"/><category term="repair drive"/><category term="reset network adapter"/><category term="reset tcp/ip"/><category term="responsive"/><category term="responsive design"/><category term="robot.txt pada blog"/><category term="rubah Akun email"/><category term="scripting"/><category term="selfi"/><category term="services"/><category term="setting"/><category term="setting ip"/><category term="sound effects"/><category term="ssh"/><category term="tanpa kulkas dingin"/><category term="technologi"/><category term="teknologi 4G"/><category term="tentang mac"/><category term="terakhir"/><category term="tesk javascript"/><category term="tidak bisa internet"/><category term="tip's memilih modem"/><category term="tips coding"/><category term="turn folder"/><category term="turn to lnk"/><category term="tweak"/><category term="tweaking"/><category term="ukuran kertas A3"/><category term="ukuran kertas A4"/><category term="update produk"/><category term="virtual environment"/><category term="virus lnk"/><category term="warna dan psikologi"/><category term="website berskala besar"/><category term="win 7"/><category term="winsock error"/><category term="xp"/><title type="text">IT-Tude</title><subtitle type="html">general IT Info </subtitle><link href="http://it-tude.blogspot.com/feeds/posts/default" rel="http://schemas.google.com/g/2005#feed" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default?redirect=false" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/" rel="alternate" type="text/html"/><link href="http://pubsubhubbub.appspot.com/" rel="hub"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default?start-index=26&amp;max-results=25&amp;redirect=false" rel="next" type="application/atom+xml"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><generator uri="http://www.blogger.com" version="7.00">Blogger</generator><openSearch:totalResults>243</openSearch:totalResults><openSearch:startIndex>1</openSearch:startIndex><openSearch:itemsPerPage>25</openSearch:itemsPerPage><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-8685597179945852308</id><published>2026-09-02T20:42:41.012-07:00</published><updated>2026-09-02T20:42:41.013-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="avatars"/><category scheme="http://www.blogger.com/atom/ns#" term="Digital"/><category scheme="http://www.blogger.com/atom/ns#" term="Web"/><title type="text">Rethinking Digital Humans: A Lightweight Approach to Web-Based Interactive Avatars</title><content type="html">&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h1 data-path-to-node="2" style="font-family: &amp;quot;Google Sans&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;br /&gt;&lt;/h1&gt;&lt;p data-path-to-node="3" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;Building responsive, interactive 3D avatars for web applications has traditionally been a daunting challenge. Developers often find themselves caught between two complex and costly extremes:&lt;/p&gt;&lt;ol data-path-to-node="4" start="1" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; padding-inline-start: 32px;"&gt;&lt;li style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;p data-path-to-node="4,0,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="4,0,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;Heavy Game Engine Pipelines:&lt;/b&gt; Workflows relying on heavy traditional engines like Unity or Unreal Engine often require dedicated streaming servers, complex WebGL exports, or high client-side hardware requirements, making integration into standard web interfaces overly cumbersome.&lt;/p&gt;&lt;/li&gt;&lt;li style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;p data-path-to-node="4,1,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="4,1,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;Expensive SaaS AI Streaming:&lt;/b&gt; Modern cloud-based AI digital human platforms offer quick results, but they introduce significant latency, rely heavily on constant video streaming, and incur expensive per-minute pricing models that scale poorly for high-traffic sites.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p data-path-to-node="5" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;Navigating through these trade-offs requires bridging multiple disciplines—3D character rigging, animation state management, real-time audio processing, and web rendering performance.&lt;/p&gt;&lt;p data-path-to-node="6" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;By deconstructing the digital human pipeline, it becomes possible to achieve dynamic, real-time 3D interaction directly inside the browser using an optimized, hybrid client-side framework.&lt;/p&gt;&lt;h3 data-path-to-node="8" style="font-family: &amp;quot;Google Sans&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;Key Architectural Pillars&lt;/h3&gt;&lt;p data-path-to-node="9" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="9" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;1. Modular 3D Avatar Foundation (Ready Player Me)&lt;/b&gt;&lt;/p&gt;&lt;ul data-path-to-node="10" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; padding-inline-start: 32px;"&gt;&lt;li style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;p data-path-to-node="10,0,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="10,0,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;Open &amp;amp; Accessible:&lt;/b&gt; Utilizes lightweight, pre-rigged humanoid &lt;code data-index-in-node="61" data-path-to-node="10,0,0" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;.glb&lt;/code&gt; assets designed specifically for web performance.&lt;/p&gt;&lt;/li&gt;&lt;li style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;p data-path-to-node="10,1,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="10,1,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;Standardized Hierarchy:&lt;/b&gt; Built on standard bone structures, ensuring full compatibility with custom animation clips authored in external software.&lt;/p&gt;&lt;/li&gt;&lt;li style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;p data-path-to-node="10,2,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="10,2,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;Integrated Morph Targets:&lt;/b&gt; Pre-configured with essential facial blendshapes required for expressions and real-time lip-syncing.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p data-path-to-node="11" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="11" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;2. Decoupled Motion via NLA Actions (Blender &amp;amp; Three.js)&lt;/b&gt;&lt;/p&gt;&lt;ul data-path-to-node="12" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; padding-inline-start: 32px;"&gt;&lt;li style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;p data-path-to-node="12,0,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="12,0,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;Non-Linear Animation (NLA):&lt;/b&gt; Body gestures (e.g., &lt;code data-index-in-node="49" data-path-to-node="12,0,0" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;Idle&lt;/code&gt;, &lt;code data-index-in-node="55" data-path-to-node="12,0,0" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;Wave&lt;/code&gt;, &lt;code data-index-in-node="61" data-path-to-node="12,0,0" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;Nod&lt;/code&gt;, &lt;code data-index-in-node="66" data-path-to-node="12,0,0" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;Explain&lt;/code&gt;) are authored in Blender as independent NLA Actions and exported within a single binary &lt;code data-index-in-node="162" data-path-to-node="12,0,0" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;.glb&lt;/code&gt; package.&lt;/p&gt;&lt;/li&gt;&lt;li style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;p data-path-to-node="12,1,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="12,1,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;Contextual Triggering:&lt;/b&gt; Three.js processes these clips dynamically via an &lt;code data-index-in-node="73" data-path-to-node="12,1,0" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;AnimationMixer&lt;/code&gt;. Gestures are triggered programmatically or extracted from context metadata generated during response synthesis (e.g., &lt;code data-index-in-node="207" data-path-to-node="12,1,0" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;[ANIM: NOD]&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p data-path-to-node="13" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="13" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;3. Dual-Layer Facial Synchronization (TTS Visemes &amp;amp; Blendshapes)&lt;/b&gt;&lt;/p&gt;&lt;ul data-path-to-node="14" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; padding-inline-start: 32px;"&gt;&lt;li style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;p data-path-to-node="14,0,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="14,0,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;Layered Deformation:&lt;/b&gt; Morph Targets (Blendshapes) operate independently of Bone Animations. Local mesh deformation for mouth movements occurs seamlessly without disrupting global head or neck rotations.&lt;/p&gt;&lt;/li&gt;&lt;li style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;p data-path-to-node="14,1,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="14,1,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;Timeline-Driven Weighting:&lt;/b&gt; Real-time viseme timeline data emitted by Text-to-Speech (TTS) engines directly controls blendshape weights in Three.js, maintaining precise lip-sync while skeletal gesture loops execute simultaneously.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p data-path-to-node="15" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="15" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;4. Native DOM Overlay &amp;amp; Web Integration&lt;/b&gt;&lt;/p&gt;&lt;ul data-path-to-node="16" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; padding-inline-start: 32px;"&gt;&lt;li style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;p data-path-to-node="16,0,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="16,0,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;Direct Canvas Rendering:&lt;/b&gt; Renders seamlessly within a standard HTML5 &lt;code data-index-in-node="68" data-path-to-node="16,0,0" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;&amp;lt;canvas&amp;gt;&lt;/code&gt; viewport managed by Three.js.&lt;/p&gt;&lt;/li&gt;&lt;li style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;p data-path-to-node="16,1,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="16,1,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;Layout Synergy:&lt;/b&gt; Configured with CSS fixed positioning and high &lt;code data-index-in-node="63" data-path-to-node="16,1,0" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;z-index&lt;/code&gt; layering, allowing the avatar to operate as an interactive, non-blocking UI widget floating above standard web application layouts.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;div&gt;&lt;span style="font-family: Google Sans Text, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: Google Sans Text, sans-serif;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/a/AVvXsEimguhrghPgLdZAz9mHV2oYypURTOixZVM7RomEDSLMJmtaYlXf0NuBwTg4VzEA7auaHD9zjMXkZuYrI-hP-dcIxt1ixU846X-kDzzQ6UzBBnu8Zln1QS2Cu6MvXidFUZfDo0GXyqFR3RE7l_JgK3m2bjOk6Xsh1xFrjxBf05CCoeSUZg9yT8Hd_c5jD2m4" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="" data-original-height="559" data-original-width="1024" height="350" src="https://blogger.googleusercontent.com/img/a/AVvXsEimguhrghPgLdZAz9mHV2oYypURTOixZVM7RomEDSLMJmtaYlXf0NuBwTg4VzEA7auaHD9zjMXkZuYrI-hP-dcIxt1ixU846X-kDzzQ6UzBBnu8Zln1QS2Cu6MvXidFUZfDo0GXyqFR3RE7l_JgK3m2bjOk6Xsh1xFrjxBf05CCoeSUZg9yT8Hd_c5jD2m4=w640-h350" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: Google Sans Text, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;div&gt;&lt;span style="font-family: Google Sans Text, sans-serif;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;&lt;h3 data-path-to-node="18" style="font-family: &amp;quot;Google Sans&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;End-to-End Execution Flow&lt;/h3&gt;&lt;ol data-path-to-node="19" start="1" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important; padding-inline-start: 32px;"&gt;&lt;li style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;p data-path-to-node="19,0,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="19,0,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;Input Signal&lt;/b&gt; &lt;span class="math-inline" data-index-in-node="13" data-math="\rightarrow" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;$\rightarrow$&lt;/span&gt; Captured via user text or audio stream.&lt;/p&gt;&lt;/li&gt;&lt;li style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;p data-path-to-node="19,1,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="19,1,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;Response Processing&lt;/b&gt; &lt;span class="math-inline" data-index-in-node="20" data-math="\rightarrow" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;$\rightarrow$&lt;/span&gt; Returns structured text, emotion/gesture metadata, and TTS audio alignment data.&lt;/p&gt;&lt;/li&gt;&lt;li style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;p data-path-to-node="19,2,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="19,2,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;Facial Layer Engine&lt;/b&gt; &lt;span class="math-inline" data-index-in-node="20" data-math="\rightarrow" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;$\rightarrow$&lt;/span&gt; Applies real-time viseme weights to facial morph targets based on audio timestamps.&lt;/p&gt;&lt;/li&gt;&lt;li style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;p data-path-to-node="19,3,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="19,3,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;Skeletal Motion Controller&lt;/b&gt; &lt;span class="math-inline" data-index-in-node="27" data-math="\rightarrow" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;$\rightarrow$&lt;/span&gt; Executes corresponding NLA gesture tracks in parallel.&lt;/p&gt;&lt;/li&gt;&lt;li style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;p data-path-to-node="19,4,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="19,4,0" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;Client-Side Synthesis&lt;/b&gt; &lt;span class="math-inline" data-index-in-node="22" data-math="\rightarrow" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;$\rightarrow$&lt;/span&gt; Composites motion and audio in real time directly inside the browser canvas.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;p data-path-to-node="21" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;Regards,&lt;/p&gt;&lt;p data-path-to-node="22" style="font-family: &amp;quot;Google Sans Text&amp;quot;, sans-serif !important; line-height: 1.15 !important; margin-top: 0px !important;"&gt;&lt;b data-index-in-node="0" data-path-to-node="22" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;Ian&lt;/b&gt; &lt;i data-index-in-node="4" data-path-to-node="22" style="line-height: 1.15 !important; margin-top: 0px !important;"&gt;(roytrix@gmail.com)&lt;/i&gt;&lt;/p&gt;</content><link href="http://it-tude.blogspot.com/feeds/8685597179945852308/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/8685597179945852308" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/8685597179945852308" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/8685597179945852308" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/09/rethinking-digital-humans-lightweight.html" rel="alternate" title="Rethinking Digital Humans: A Lightweight Approach to Web-Based Interactive Avatars" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/a/AVvXsEimguhrghPgLdZAz9mHV2oYypURTOixZVM7RomEDSLMJmtaYlXf0NuBwTg4VzEA7auaHD9zjMXkZuYrI-hP-dcIxt1ixU846X-kDzzQ6UzBBnu8Zln1QS2Cu6MvXidFUZfDo0GXyqFR3RE7l_JgK3m2bjOk6Xsh1xFrjxBf05CCoeSUZg9yT8Hd_c5jD2m4=s72-w640-h350-c" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-4455442271277925110</id><published>2026-08-26T09:43:52.704-07:00</published><updated>2026-08-26T14:41:52.031-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Blender"/><category scheme="http://www.blogger.com/atom/ns#" term="blender Script"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type="text">Blender: Generating Seamless Flag Wave Animation from Base Pose</title><content type="html">&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h3 style="text-align: left;"&gt;&lt;span style="font-weight: normal;"&gt;Generating Seamless Flag Wave Animation from Base Pose &lt;br /&gt;(7-Bone Setup)&amp;nbsp;&lt;/span&gt;&lt;span style="font-weight: normal;"&gt;Script Blender&lt;/span&gt;&lt;/h3&gt;&lt;p data-path-to-node="3"&gt;Creating natural-looking flag wave animations in Blender often requires manual keyframing across multiple bones, which can be time-consuming to loop perfectly.&lt;/p&gt;&lt;p data-path-to-node="4"&gt;This Python script solves that problem by generating a continuous, looping flag wave animation automatically. It works by taking the initial pose of a 7-bone armature at &lt;b data-index-in-node="170" data-path-to-node="4"&gt;Frame 1&lt;/b&gt; as a baseline profile, sampling that spatial wave profile across the timeline, and applying it smoothly to subsequent keyframes (&lt;b data-index-in-node="307" data-path-to-node="4"&gt;Frames 25, 50, 75, and 100&lt;/b&gt;).&lt;/p&gt;&lt;h3 data-path-to-node="6"&gt;Key Features &amp;amp; How It Works:&lt;/h3&gt;&lt;ol data-path-to-node="7" start="1"&gt;&lt;li&gt;&lt;p data-path-to-node="7,0,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="7,0,0"&gt;Base Pose Sampling&lt;/b&gt;: Reads the current &lt;b data-index-in-node="38" data-path-to-node="7,0,0"&gt;Y Location&lt;/b&gt; of all 7 bones at Frame 1 to create the initial wave shape.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="7,1,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="7,1,0"&gt;Traveling Profile Algorithm&lt;/b&gt;: Shifts the baseline wave profile along the bone chain across the timeline to simulate wave movement.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="7,2,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="7,2,0"&gt;Perfect Loop Guarantee&lt;/b&gt;: Forces &lt;b data-index-in-node="31" data-path-to-node="7,2,0"&gt;Frame 100&lt;/b&gt; to match Frame 1 exactly, ensuring a 100% seamless looping animation (Frames 1–100).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="7,3,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="7,3,0"&gt;Automatic Bezier Interpolation&lt;/b&gt;: Sets keyframe handles to &lt;code data-index-in-node="57" data-path-to-node="7,3,0"&gt;BEZIER&lt;/code&gt; with &lt;code data-index-in-node="69" data-path-to-node="7,3,0"&gt;AUTO&lt;/code&gt; handles to provide smooth interpolation without manual graph editing.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 data-path-to-node="9"&gt;Kode Script (Python - Blender API)&lt;/h3&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;pre&gt;&lt;code class="language-python"&gt;import bpy
import math

# ============================================================
# 7-BONE FLAG WAVE FROM FRAME-1 POSE
#
# Armature : Armature.7
# Bones    : Bone.1 - Bone.7
#
# Frame 1   = Reads actual base pose
# Frame 25  = Wave shift
# Frame 50  = Wave shift
# Frame 75  = Wave shift
# Frame 100 = EXACT Frame 1 (Perfect Loop)
#
# Affects Y Location only
# ============================================================

ARMATURE_NAME = "Armature.7"

BONE_NAMES = [
    "Bone.1",
    "Bone.2",
    "Bone.3",
    "Bone.4",
    "Bone.5",
    "Bone.6",
    "Bone.7",
]

KEY_FRAMES = [1, 25, 50, 75, 100]

START_FRAME = 1
END_FRAME = 100

# ============================================================
# GET ARMATURE
# ============================================================

arm = bpy.data.objects.get(ARMATURE_NAME)

if arm is None:
    raise Exception(f"Armature '{ARMATURE_NAME}' not found.")

# ============================================================
# READ FRAME 1 BASE POSE
# ============================================================

bpy.context.scene.frame_set(1)

BASE_Y = []

print("")
print("========================================")
print("FRAME 1 SOURCE POSE")
print("========================================")

for bone_name in BONE_NAMES:
    bone = arm.pose.bones.get(bone_name)

    if bone is None:
        raise Exception(f"Bone '{bone_name}' not found.")

    y = bone.location.y
    BASE_Y.append(y)

    print(f"{bone_name:7s} = {y:+.5f}")

# ============================================================
# PROFILE SAMPLER
#
# Reads 7-bone profile cyclically.
# Can sample positions between two bones.
# ============================================================

def sample_profile(values, position):
    count = len(values)
    position = position % count

    i0 = int(math.floor(position))
    i1 = (i0 + 1) % count
    frac = position - i0

    return values[i0] * (1.0 - frac) + values[i1] * frac

# ============================================================
# DELETE OLD Y ANIMATION
#
# Only targets Bone.1 - Bone.7 Y Location.
# ============================================================

if arm.animation_data and arm.animation_data.action:
    action = arm.animation_data.action

    for fc in list(action.fcurves):
        if fc.array_index != 1:
            continue

        for bone_name in BONE_NAMES:
            target = f'pose.bones["{bone_name}"].location'

            if fc.data_path == target:
                action.fcurves.remove(fc)
                break

# ============================================================
# CREATE WAVE
# ============================================================

BONE_COUNT = len(BONE_NAMES)

for frame in KEY_FRAMES:
    bpy.context.scene.frame_set(frame)

    # Normalized timeline: frame 1 = 0, frame 100 = 1
    t = (frame - START_FRAME) / (END_FRAME - START_FRAME)

    # Profile travels one complete cycle
    shift = t * BONE_COUNT

    for bone_index, bone_name in enumerate(BONE_NAMES):
        bone = arm.pose.bones.get(bone_name)

        if bone is None:
            continue

        # Traveling Profile: "-" moves wave from Bone.1 to Bone.7
        # Change "-" to "+" for reverse direction
        source_position = bone_index - shift
        y = sample_profile(BASE_Y, source_position)

        # APPLY KEYFRAME
        bone.location.y = y
        bone.keyframe_insert(data_path="location", index=1, frame=frame)

# ============================================================
# FORCE FRAME 100 = EXACT FRAME 1
# ============================================================

bpy.context.scene.frame_set(100)

for bone_name, original_y in zip(BONE_NAMES, BASE_Y):
    bone = arm.pose.bones.get(bone_name)

    if bone is None:
        continue

    bone.location.y = original_y
    bone.keyframe_insert(data_path="location", index=1, frame=100)

# ============================================================
# SMOOTH TEMPORAL INTERPOLATION
# ============================================================

if arm.animation_data and arm.animation_data.action:
    action = arm.animation_data.action

    for fc in action.fcurves:
        if fc.array_index != 1:
            continue

        valid = False
        for bone_name in BONE_NAMES:
            if fc.data_path == f'pose.bones["{bone_name}"].location':
                valid = True
                break

        if not valid:
            continue

        for kp in fc.keyframe_points:
            kp.interpolation = 'BEZIER'
            kp.handle_left_type = 'AUTO'
            kp.handle_right_type = 'AUTO'

# ============================================================
# TIMELINE SETUP
# ============================================================

bpy.context.scene.frame_start = 1
bpy.context.scene.frame_end = 100
bpy.context.scene.frame_set(1)

print("")
print("========================================")
print("7-BONE FLAG WAVE CREATED")
print("========================================")
print("Frame 1   = source pose")
print("Frame 25  = traveling wave")
print("Frame 50  = traveling wave")
print("Frame 75  = traveling wave")
print("Frame 100 = exact Frame 1")
print("========================================")&lt;/code&gt;&lt;/pre&gt;&lt;br /&gt;</content><link href="http://it-tude.blogspot.com/feeds/4455442271277925110/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/4455442271277925110" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/4455442271277925110" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/4455442271277925110" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/08/script-blender-generating-seamless-flag.html" rel="alternate" title="Blender: Generating Seamless Flag Wave Animation from Base Pose" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-4690188603136010981</id><published>2026-08-25T17:55:46.710-07:00</published><updated>2026-08-25T17:55:46.710-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Blender"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><category scheme="http://www.blogger.com/atom/ns#" term="scripting"/><title type="text">Script Blender: Smooth Auto-Weighting Menggunakan Gaussian Falloff</title><content type="html">&lt;p&gt;&lt;b&gt;&amp;nbsp;Script Blender: &lt;br /&gt;Smooth Auto-Weighting Menggunakan Gaussian Falloff untuk 7 Bone pada Plane&lt;/b&gt;&lt;br /&gt;--&lt;br /&gt;&lt;/p&gt;&lt;p data-path-to-node="4"&gt;Pernahkah Anda merasa kesulitan saat melakukan &lt;i data-index-in-node="47" data-path-to-node="4"&gt;weight painting&lt;/i&gt; manual di Blender, terutama untuk objek seperti bendera, kain, atau tali yang membutuhkan transisi antar &lt;i data-index-in-node="168" data-path-to-node="4"&gt;bone&lt;/i&gt; yang sangat mulus?&lt;/p&gt;&lt;p data-path-to-node="5"&gt;&lt;i data-index-in-node="0" data-path-to-node="5"&gt;Weight painting&lt;/i&gt; manual sering kali menghasilkan lekukan yang kaku (&lt;i data-index-in-node="67" data-path-to-node="5"&gt;sharp/jagged&lt;/i&gt;) saat dianimasikan. Metode default Blender (&lt;i data-index-in-node="124" data-path-to-node="5"&gt;Automatic Weights&lt;/i&gt;) pun terkadang kurang presisi jika bentuk mesh kita sederhana seperti &lt;i data-index-in-node="212" data-path-to-node="5"&gt;Plane&lt;/i&gt;.&lt;/p&gt;&lt;p data-path-to-node="6"&gt;Artikel ini membagikan script Python khusus untuk Blender yang berfungsi melakukan &lt;b data-index-in-node="83" data-path-to-node="6"&gt;automatic weight calculation secara presisi menggunakan distribusi kurva Gaussian (Gaussian Falloff)&lt;/b&gt;. Script ini dirancang untuk mendistribusikan &lt;i data-index-in-node="229" data-path-to-node="6"&gt;weight&lt;/i&gt; secara otomatis pada 7 &lt;i data-index-in-node="259" data-path-to-node="6"&gt;bone&lt;/i&gt; di sepanjang objek &lt;i data-index-in-node="283" data-path-to-node="6"&gt;Plane&lt;/i&gt;, sekaligus memastikan total &lt;i data-index-in-node="317" data-path-to-node="6"&gt;weight&lt;/i&gt; pada setiap &lt;i data-index-in-node="336" data-path-to-node="6"&gt;vertex&lt;/i&gt; selalu &lt;b data-index-in-node="350" data-path-to-node="6"&gt;ter-normalisasi sempurna (sama dengan 1.0)&lt;/b&gt; tanpa mengganggu &lt;i data-index-in-node="410" data-path-to-node="6"&gt;keyframe&lt;/i&gt; atau animasi yang sudah ada.&lt;/p&gt;&lt;h3 data-path-to-node="8"&gt;Cara Kerja Script:&lt;/h3&gt;&lt;ol data-path-to-node="9" start="1"&gt;&lt;li&gt;&lt;p data-path-to-node="9,0,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="9,0,0"&gt;Deteksi Sumbu Otomatis&lt;/b&gt;: Membaca posisi awal (&lt;i data-index-in-node="45" data-path-to-node="9,0,0"&gt;Bone.1&lt;/i&gt;) hingga akhir (&lt;i data-index-in-node="67" data-path-to-node="9,0,0"&gt;Bone.7&lt;/i&gt;) lalu mendeteksi arah sumbu tanpa peduli orientasi objek (X, Y, atau Z).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="9,1,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="9,1,0"&gt;Kalkulasi Gaussian Falloff&lt;/b&gt;: Menghitung pengaruh (&lt;i data-index-in-node="49" data-path-to-node="9,1,0"&gt;influence&lt;/i&gt;) tiap &lt;i data-index-in-node="65" data-path-to-node="9,1,0"&gt;bone&lt;/i&gt; ke setiap &lt;i data-index-in-node="80" data-path-to-node="9,1,0"&gt;vertex&lt;/i&gt; menggunakan fungsi distribusi Gaussian.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="9,2,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="9,2,0"&gt;Normalisasi Weight&lt;/b&gt;: Memastikan penjumlahan seluruh &lt;i data-index-in-node="51" data-path-to-node="9,2,0"&gt;weight&lt;/i&gt; dari &lt;i data-index-in-node="63" data-path-to-node="9,2,0"&gt;Bone.1&lt;/i&gt; hingga &lt;i data-index-in-node="77" data-path-to-node="9,2,0"&gt;Bone.7&lt;/i&gt; pada setiap &lt;i data-index-in-node="96" data-path-to-node="9,2,0"&gt;vertex&lt;/i&gt; bernilai tepat &lt;code data-index-in-node="118" data-path-to-node="9,2,0"&gt;1.0&lt;/code&gt;.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="9,3,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="9,3,0"&gt;Proteksi Animasi&lt;/b&gt;: Meng-update &lt;i data-index-in-node="30" data-path-to-node="9,3,0"&gt;vertex group&lt;/i&gt; tanpa menyentuh data animasi atau &lt;i data-index-in-node="77" data-path-to-node="9,3,0"&gt;keyframe&lt;/i&gt; yang sudah tersimpan.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;h3 data-path-to-node="11"&gt;Kode Script (Python - Blender API)&lt;/h3&gt;&lt;div _ngcontent-ng-c1203130217="" class="code-block ng-tns-c1203130217-19 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahcKEwikgfrrib2WAxUAAAAAHQAAAAAQew" decode-data-ved="1" jslog="223238;track:impression,attention;BardVeMetadataKey:[[&amp;quot;r_1bcc7f624b8df1ea&amp;quot;,&amp;quot;c_51b64829202e3e28&amp;quot;,null,&amp;quot;rc_ed063d7fa20c1130&amp;quot;,null,null,&amp;quot;id&amp;quot;,null,1,null,null,1,0]]"&gt;&lt;!----&gt;&lt;div _ngcontent-ng-c1203130217="" class="formatted-code-block-internal-container ng-tns-c1203130217-19"&gt;&lt;div _ngcontent-ng-c1203130217="" class="animated-opacity ng-tns-c1203130217-19"&gt;&lt;div _ngcontent-ng-c1203130217="" class="code-block-decoration header-formatted gds-emphasized-body-m ng-tns-c1203130217-19 ng-star-inserted"&gt;&lt;span _ngcontent-ng-c1203130217="" class="ng-tns-c1203130217-19"&gt;Python&lt;/span&gt;&lt;div _ngcontent-ng-c1203130217="" class="buttons ng-tns-c1203130217-19 ng-star-inserted"&gt;&lt;gem-icon-button _ngcontent-ng-c1203130217="" _nghost-ng-c3763868169="" aria-describedby="cdk-describedby-message-ng-1-31" arialabel="Download code" cdk-describedby-host="ng-1" class="mat-mdc-tooltip-trigger download-button ng-tns-c1203130217-19 gem-button gem-button-badge-size-small gem-button-size-small gem-button-type-on-surface lm-enabled ng-star-inserted" fonticonname="arrow_circle_down" gemtooltip="Download code" size="small" tabindex="-1" theme="lm" type="onSurface"&gt;&lt;!----&gt;&lt;!----&gt;&lt;button _ngcontent-ng-c3763868169="" aria-label="Download code" class="mdc-icon-button mat-mdc-icon-button mat-mdc-button-base mat-badge mat-unthemed mat-badge-overlap mat-badge-above mat-badge-after mat-badge-small mat-badge-hidden ng-star-inserted" jslog="305704;track:generic_click,impression" mat-ripple-loader-centered="" mat-ripple-loader-class-name="mat-mdc-button-ripple" mat-ripple-loader-uninitialized="" matbadgeposition="after" maticonbutton=""&gt;&lt;span class="mat-mdc-button-persistent-ripple mdc-icon-button__ripple"&gt;&lt;/span&gt;&lt;gem-icon _ngcontent-ng-c3763868169="" _nghost-ng-c2831891020=""&gt;&lt;mat-icon _ngcontent-ng-c2831891020="" aria-hidden="true" class="mat-icon notranslate lm-icon-l lumi-symbols mat-ligature-font mat-icon-no-color ng-star-inserted" data-mat-icon-name="arrow_circle_down" data-mat-icon-namespace="lumi-symbols" data-mat-icon-type="font" fonticon="arrow_circle_down" role="img"&gt;&lt;/mat-icon&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;/gem-icon&gt;&lt;!----&gt;&lt;span class="mat-focus-indicator"&gt;&lt;/span&gt;&lt;span class="mat-mdc-button-touch-target"&gt;&lt;/span&gt;&lt;/button&gt;&lt;!----&gt;&lt;!----&gt;&lt;/gem-icon-button&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;gem-icon-button _ngcontent-ng-c1203130217="" _nghost-ng-c3763868169="" aria-describedby="cdk-describedby-message-ng-1-32" arialabel="Copy code" cdk-describedby-host="ng-1" class="mat-mdc-tooltip-trigger copy-button ng-tns-c1203130217-19 gem-button gem-button-badge-size-small gem-button-size-small gem-button-type-on-surface lm-enabled ng-star-inserted" data-test-id="gem-copy-button" fonticonname="copy" gemtooltip="Copy code" size="small" tabindex="-1" theme="lm" type="onSurface"&gt;&lt;!----&gt;&lt;!----&gt;&lt;button _ngcontent-ng-c3763868169="" aria-label="Copy code" class="mdc-icon-button mat-mdc-icon-button mat-mdc-button-base mat-badge mat-unthemed mat-badge-overlap mat-badge-above mat-badge-after mat-badge-small mat-badge-hidden ng-star-inserted" jslog="179062;track:generic_click,impression;BardVeMetadataKey:[[&amp;quot;r_1bcc7f624b8df1ea&amp;quot;,&amp;quot;c_51b64829202e3e28&amp;quot;,null,&amp;quot;rc_ed063d7fa20c1130&amp;quot;,null,null,&amp;quot;id&amp;quot;,null,1,null,null,1,0]];mutable:true" mat-ripple-loader-centered="" mat-ripple-loader-class-name="mat-mdc-button-ripple" mat-ripple-loader-uninitialized="" matbadgeposition="after" maticonbutton=""&gt;&lt;span class="mat-mdc-button-persistent-ripple mdc-icon-button__ripple"&gt;&lt;/span&gt;&lt;gem-icon _ngcontent-ng-c3763868169="" _nghost-ng-c2831891020=""&gt;&lt;mat-icon _ngcontent-ng-c2831891020="" aria-hidden="true" class="mat-icon notranslate lm-icon-l lumi-symbols mat-ligature-font mat-icon-no-color ng-star-inserted" data-mat-icon-name="copy" data-mat-icon-namespace="lumi-symbols" data-mat-icon-type="font" fonticon="copy" role="img"&gt;&lt;/mat-icon&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;/gem-icon&gt;&lt;!----&gt;&lt;span class="mat-focus-indicator"&gt;&lt;/span&gt;&lt;span class="mat-mdc-button-touch-target"&gt;&lt;/span&gt;&lt;/button&gt;&lt;!----&gt;&lt;!----&gt;&lt;/gem-icon-button&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;/div&gt;&lt;!----&gt;&lt;!----&gt;&lt;/div&gt;&lt;!----&gt;&lt;pre _ngcontent-ng-c1203130217="" class="ng-tns-c1203130217-19"&gt;&lt;code _ngcontent-ng-c1203130217="" class="code-container formatted ng-tns-c1203130217-19" data-test-id="code-content" role="text"&gt;&lt;span class="hljs-keyword"&gt;import&lt;/span&gt; bpy
&lt;span class="hljs-keyword"&gt;import&lt;/span&gt; math

&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# SMOOTH GAUSSIAN AUTO-WEIGHT&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# Plane.005 + Armature.7&lt;/span&gt;
&lt;span class="hljs-comment"&gt;#&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# Tujuan:&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# - Weight Bone.1 ... Bone.7 dibuat sangat smooth&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# - Antar bone overlap&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# - Total weight per vertex = 1.0&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# - Tidak menyentuh animation/keyframe&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;

MESH_NAME = &lt;span class="hljs-string"&gt;"Plane.005"&lt;/span&gt;
ARMATURE_NAME = &lt;span class="hljs-string"&gt;"Armature.7"&lt;/span&gt;

BONE_NAMES = [
    &lt;span class="hljs-string"&gt;"Bone.1"&lt;/span&gt;,
    &lt;span class="hljs-string"&gt;"Bone.2"&lt;/span&gt;,
    &lt;span class="hljs-string"&gt;"Bone.3"&lt;/span&gt;,
    &lt;span class="hljs-string"&gt;"Bone.4"&lt;/span&gt;,
    &lt;span class="hljs-string"&gt;"Bone.5"&lt;/span&gt;,
    &lt;span class="hljs-string"&gt;"Bone.6"&lt;/span&gt;,
    &lt;span class="hljs-string"&gt;"Bone.7"&lt;/span&gt;,
]

&lt;span class="hljs-comment"&gt;# ------------------------------------------------------------&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# WIDTH OF INFLUENCE&lt;/span&gt;
&lt;span class="hljs-comment"&gt;#&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# 0.75 = lebih lokal / tajam&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# 1.00 = balanced&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# 1.25 = lebih silky / overlap lebar&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# 1.50 = sangat lembut&lt;/span&gt;
&lt;span class="hljs-comment"&gt;#&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# Mulai 1.25 untuk bendera kita.&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# ------------------------------------------------------------&lt;/span&gt;

SIGMA = &lt;span class="hljs-number"&gt;1.25&lt;/span&gt;

&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# GET OBJECTS&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;

obj = bpy.data.objects.get(MESH_NAME)
arm = bpy.data.objects.get(ARMATURE_NAME)

&lt;span class="hljs-keyword"&gt;if&lt;/span&gt; obj &lt;span class="hljs-keyword"&gt;is&lt;/span&gt; &lt;span class="hljs-literal"&gt;None&lt;/span&gt;:
    &lt;span class="hljs-keyword"&gt;raise&lt;/span&gt; Exception(&lt;span class="hljs-string"&gt;f"Mesh '&lt;span class="hljs-subst"&gt;{MESH_NAME}&lt;/span&gt;' tidak ditemukan"&lt;/span&gt;)

&lt;span class="hljs-keyword"&gt;if&lt;/span&gt; arm &lt;span class="hljs-keyword"&gt;is&lt;/span&gt; &lt;span class="hljs-literal"&gt;None&lt;/span&gt;:
    &lt;span class="hljs-keyword"&gt;raise&lt;/span&gt; Exception(&lt;span class="hljs-string"&gt;f"Armature '&lt;span class="hljs-subst"&gt;{ARMATURE_NAME}&lt;/span&gt;' tidak ditemukan"&lt;/span&gt;)

&lt;span class="hljs-keyword"&gt;if&lt;/span&gt; obj.&lt;span class="hljs-built_in"&gt;type&lt;/span&gt; != &lt;span class="hljs-string"&gt;'MESH'&lt;/span&gt;:
    &lt;span class="hljs-keyword"&gt;raise&lt;/span&gt; Exception(&lt;span class="hljs-string"&gt;f"'&lt;span class="hljs-subst"&gt;{MESH_NAME}&lt;/span&gt;' bukan Mesh"&lt;/span&gt;)

&lt;span class="hljs-keyword"&gt;if&lt;/span&gt; arm.&lt;span class="hljs-built_in"&gt;type&lt;/span&gt; != &lt;span class="hljs-string"&gt;'ARMATURE'&lt;/span&gt;:
    &lt;span class="hljs-keyword"&gt;raise&lt;/span&gt; Exception(&lt;span class="hljs-string"&gt;f"'&lt;span class="hljs-subst"&gt;{ARMATURE_NAME}&lt;/span&gt;' bukan Armature"&lt;/span&gt;)

&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# FORCE OBJECT MODE&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;

&lt;span class="hljs-keyword"&gt;if&lt;/span&gt; bpy.context.&lt;span class="hljs-built_in"&gt;object&lt;/span&gt;:
    &lt;span class="hljs-keyword"&gt;try&lt;/span&gt;:
        bpy.ops.&lt;span class="hljs-built_in"&gt;object&lt;/span&gt;.mode_set(mode=&lt;span class="hljs-string"&gt;'OBJECT'&lt;/span&gt;)
    &lt;span class="hljs-keyword"&gt;except&lt;/span&gt;:
        &lt;span class="hljs-keyword"&gt;pass&lt;/span&gt;

&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# GET BONE POSITIONS&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# Kita baca posisi bone dalam LOCAL SPACE mesh.&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;

bone_positions = []

&lt;span class="hljs-keyword"&gt;for&lt;/span&gt; bone_name &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; BONE_NAMES:
    bone = arm.data.bones.get(bone_name)

    &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; bone &lt;span class="hljs-keyword"&gt;is&lt;/span&gt; &lt;span class="hljs-literal"&gt;None&lt;/span&gt;:
        &lt;span class="hljs-keyword"&gt;raise&lt;/span&gt; Exception(&lt;span class="hljs-string"&gt;f"Bone '&lt;span class="hljs-subst"&gt;{bone_name}&lt;/span&gt;' tidak ditemukan"&lt;/span&gt;)

    &lt;span class="hljs-comment"&gt;# bone head -&amp;gt; world&lt;/span&gt;
    world_pos = arm.matrix_world @ bone.head_local

    &lt;span class="hljs-comment"&gt;# world -&amp;gt; mesh local&lt;/span&gt;
    mesh_pos = obj.matrix_world.inverted() @ world_pos

    bone_positions.append(mesh_pos)

&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# DETECT MAIN AXIS&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# Cari sumbu sepanjang Bone.1 -&amp;gt; Bone.7.&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# Jadi script tidak bergantung apakah mesh memanjang di X/Y/Z.&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;

start = bone_positions[&lt;span class="hljs-number"&gt;0&lt;/span&gt;]
end = bone_positions[-&lt;span class="hljs-number"&gt;1&lt;/span&gt;]

axis = end - start

&lt;span class="hljs-keyword"&gt;if&lt;/span&gt; axis.length == &lt;span class="hljs-number"&gt;0&lt;/span&gt;:
    &lt;span class="hljs-keyword"&gt;raise&lt;/span&gt; Exception(&lt;span class="hljs-string"&gt;"Bone.1 dan Bone.7 berada di posisi yang sama"&lt;/span&gt;)

axis.normalize()

&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# PROJECT BONE POSITIONS TO 1D&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;

bone_axis_pos = []

&lt;span class="hljs-keyword"&gt;for&lt;/span&gt; pos &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; bone_positions:
    relative = pos - start
    projected = relative.dot(axis)
    bone_axis_pos.append(projected)

print(&lt;span class="hljs-string"&gt;"\n========================================"&lt;/span&gt;)
print(&lt;span class="hljs-string"&gt;"BONE POSITION ALONG FLAG"&lt;/span&gt;)
print(&lt;span class="hljs-string"&gt;"========================================"&lt;/span&gt;)

&lt;span class="hljs-keyword"&gt;for&lt;/span&gt; name, p &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; &lt;span class="hljs-built_in"&gt;zip&lt;/span&gt;(BONE_NAMES, bone_axis_pos):
    print(&lt;span class="hljs-string"&gt;f"&lt;span class="hljs-subst"&gt;{name:7s}&lt;/span&gt;: &lt;span class="hljs-subst"&gt;{p:+&lt;span class="hljs-number"&gt;.5&lt;/span&gt;f}&lt;/span&gt;"&lt;/span&gt;)

&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# AVERAGE BONE SPACING&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# Digunakan agar SIGMA relatif terhadap jarak antar bone.&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;

distances = []

&lt;span class="hljs-keyword"&gt;for&lt;/span&gt; i &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; &lt;span class="hljs-built_in"&gt;range&lt;/span&gt;(&lt;span class="hljs-built_in"&gt;len&lt;/span&gt;(bone_axis_pos) - &lt;span class="hljs-number"&gt;1&lt;/span&gt;):
    d = &lt;span class="hljs-built_in"&gt;abs&lt;/span&gt;(bone_axis_pos[i + &lt;span class="hljs-number"&gt;1&lt;/span&gt;] - bone_axis_pos[i])
    &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; d &amp;gt; &lt;span class="hljs-number"&gt;0.000001&lt;/span&gt;:
        distances.append(d)

&lt;span class="hljs-keyword"&gt;if&lt;/span&gt; &lt;span class="hljs-keyword"&gt;not&lt;/span&gt; distances:
    &lt;span class="hljs-keyword"&gt;raise&lt;/span&gt; Exception(&lt;span class="hljs-string"&gt;"Tidak bisa menentukan jarak antar bone"&lt;/span&gt;)

average_spacing = &lt;span class="hljs-built_in"&gt;sum&lt;/span&gt;(distances) / &lt;span class="hljs-built_in"&gt;len&lt;/span&gt;(distances)
sigma_distance = average_spacing * SIGMA

print(&lt;span class="hljs-string"&gt;"\nAverage bone spacing :"&lt;/span&gt;, average_spacing)
print(&lt;span class="hljs-string"&gt;"Gaussian sigma       :"&lt;/span&gt;, sigma_distance)

&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# CREATE / GET VERTEX GROUPS&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;

groups = {}

&lt;span class="hljs-keyword"&gt;for&lt;/span&gt; bone_name &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; BONE_NAMES:
    vg = obj.vertex_groups.get(bone_name)
    &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; vg &lt;span class="hljs-keyword"&gt;is&lt;/span&gt; &lt;span class="hljs-literal"&gt;None&lt;/span&gt;:
        vg = obj.vertex_groups.new(name=bone_name)
    groups[bone_name] = vg

&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# CLEAR OLD WEIGHTS&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# Hanya Bone.1 ... Bone.7.&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# Vertex group lain TIDAK disentuh.&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;

all_indices = [v.index &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; v &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; obj.data.vertices]

&lt;span class="hljs-keyword"&gt;for&lt;/span&gt; bone_name &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; BONE_NAMES:
    vg = groups[bone_name]
    &lt;span class="hljs-keyword"&gt;try&lt;/span&gt;:
        vg.remove(all_indices)
    &lt;span class="hljs-keyword"&gt;except&lt;/span&gt;:
        &lt;span class="hljs-keyword"&gt;pass&lt;/span&gt;

&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# GAUSSIAN FUNCTION&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;

&lt;span class="hljs-function"&gt;&lt;span class="hljs-keyword"&gt;def&lt;/span&gt; &lt;span class="hljs-title"&gt;gaussian&lt;/span&gt;(&lt;span class="hljs-params"&gt;distance, sigma&lt;/span&gt;):&lt;/span&gt;
    &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; sigma &amp;lt;= &lt;span class="hljs-number"&gt;0&lt;/span&gt;:
        &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; &lt;span class="hljs-number"&gt;0.0&lt;/span&gt;
    &lt;span class="hljs-keyword"&gt;return&lt;/span&gt; math.exp(-&lt;span class="hljs-number"&gt;0.5&lt;/span&gt; * (distance / sigma) ** &lt;span class="hljs-number"&gt;2&lt;/span&gt;)

&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# CALCULATE WEIGHTS&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;

print(&lt;span class="hljs-string"&gt;"\nCalculating smooth weights..."&lt;/span&gt;)

&lt;span class="hljs-keyword"&gt;for&lt;/span&gt; vertex &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; obj.data.vertices:

    &lt;span class="hljs-comment"&gt;# vertex position projected along flag axis&lt;/span&gt;
    relative = vertex.co - start
    vertex_axis_pos = relative.dot(axis)

    raw_weights = []

    &lt;span class="hljs-comment"&gt;# Gaussian influence from every bone&lt;/span&gt;
    &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; bone_pos &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; bone_axis_pos:
        distance = vertex_axis_pos - bone_pos
        w = gaussian(distance, sigma_distance)
        raw_weights.append(w)

    &lt;span class="hljs-comment"&gt;# NORMALIZE (Bone.1 + ... + Bone.7 = 1.0)&lt;/span&gt;
    total = &lt;span class="hljs-built_in"&gt;sum&lt;/span&gt;(raw_weights)

    &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; total &amp;lt;= &lt;span class="hljs-number"&gt;0.0000001&lt;/span&gt;:
        &lt;span class="hljs-keyword"&gt;continue&lt;/span&gt;

    normalized = [w / total &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; w &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; raw_weights]

    &lt;span class="hljs-comment"&gt;# WRITE WEIGHTS&lt;/span&gt;
    &lt;span class="hljs-keyword"&gt;for&lt;/span&gt; bone_name, weight &lt;span class="hljs-keyword"&gt;in&lt;/span&gt; &lt;span class="hljs-built_in"&gt;zip&lt;/span&gt;(BONE_NAMES, normalized):
        &lt;span class="hljs-comment"&gt;# Jangan tulis weight sangat kecil&lt;/span&gt;
        &lt;span class="hljs-keyword"&gt;if&lt;/span&gt; weight &amp;gt; &lt;span class="hljs-number"&gt;0.0001&lt;/span&gt;:
            groups[bone_name].add([vertex.index], weight, &lt;span class="hljs-string"&gt;'REPLACE'&lt;/span&gt;)

&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# UPDATE&lt;/span&gt;
&lt;span class="hljs-comment"&gt;# ============================================================&lt;/span&gt;

obj.data.update()

bpy.context.view_layer.objects.active = obj
obj.select_set(&lt;span class="hljs-literal"&gt;True&lt;/span&gt;)

print(&lt;span class="hljs-string"&gt;"\n========================================"&lt;/span&gt;)
print(&lt;span class="hljs-string"&gt;"SMOOTH 7-BONE WEIGHT COMPLETE"&lt;/span&gt;)
print(&lt;span class="hljs-string"&gt;"========================================"&lt;/span&gt;)
print(&lt;span class="hljs-string"&gt;f"Mesh       : &lt;span class="hljs-subst"&gt;{MESH_NAME}&lt;/span&gt;"&lt;/span&gt;)
print(&lt;span class="hljs-string"&gt;f"Armature   : &lt;span class="hljs-subst"&gt;{ARMATURE_NAME}&lt;/span&gt;"&lt;/span&gt;)
print(&lt;span class="hljs-string"&gt;f"Sigma      : &lt;span class="hljs-subst"&gt;{SIGMA}&lt;/span&gt;"&lt;/span&gt;)
print(&lt;span class="hljs-string"&gt;"Total weight per vertex normalized = 1"&lt;/span&gt;)
print(&lt;span class="hljs-string"&gt;"Animation untouched"&lt;/span&gt;)
print(&lt;span class="hljs-string"&gt;"========================================"&lt;/span&gt;)
&lt;/code&gt;&lt;/pre&gt;&lt;!----&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;h3 data-path-to-node="14"&gt;Cara Penggunaan di Blender:&lt;/h3&gt;&lt;p&gt;&lt;response-element class="no-md" ng-version="0.0.0-PLACEHOLDER"&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;code-block _nghost-ng-c1203130217="" class="ng-tns-c1203130217-19 enable-luminous-code-block ng-star-inserted"&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;/code-block&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;/response-element&gt;&lt;/p&gt;&lt;ol data-path-to-node="15" start="1"&gt;&lt;li&gt;&lt;p data-path-to-node="15,0,0"&gt;Buka tab &lt;b data-index-in-node="9" data-path-to-node="15,0,0"&gt;Scripting&lt;/b&gt; di Blender.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="15,1,0"&gt;Buat file baru (&lt;i data-index-in-node="16" data-path-to-node="15,1,0"&gt;Text -&amp;gt; New&lt;/i&gt;) lalu &lt;i data-index-in-node="34" data-path-to-node="15,1,0"&gt;paste&lt;/i&gt; kode di atas.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="15,2,0"&gt;Sesuaikan variabel &lt;code data-index-in-node="19" data-path-to-node="15,2,0"&gt;MESH_NAME&lt;/code&gt; dan &lt;code data-index-in-node="33" data-path-to-node="15,2,0"&gt;ARMATURE_NAME&lt;/code&gt; dengan nama objek yang kamu miliki di scene.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="15,3,0"&gt;Kamu juga bisa mengubah nilai &lt;code data-index-in-node="30" data-path-to-node="15,3,0"&gt;SIGMA&lt;/code&gt; jika ingin transisi lebih tajam (misal &lt;code data-index-in-node="75" data-path-to-node="15,3,0"&gt;0.75&lt;/code&gt;) atau lebih mulus/lebar (misal &lt;code data-index-in-node="111" data-path-to-node="15,3,0"&gt;1.50&lt;/code&gt;).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="15,4,0"&gt;Klik ikon &lt;b data-index-in-node="10" data-path-to-node="15,4,0"&gt;Play / Run Script&lt;/b&gt;. Hasil &lt;i data-index-in-node="35" data-path-to-node="15,4,0"&gt;weight&lt;/i&gt; baru akan langsung di-apply pada objek mesh kamu.&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;</content><link href="http://it-tude.blogspot.com/feeds/4690188603136010981/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/4690188603136010981" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/4690188603136010981" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/4690188603136010981" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/08/script-blender-smooth-auto-weighting.html" rel="alternate" title="Script Blender: Smooth Auto-Weighting Menggunakan Gaussian Falloff" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-1133832483464789672</id><published>2026-08-22T11:38:49.813-07:00</published><updated>2026-08-22T11:38:49.814-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="animasi"/><category scheme="http://www.blogger.com/atom/ns#" term="Blender"/><title type="text">Basic Bone For Flag Animation</title><content type="html">&lt;div style="text-align: left;"&gt;&lt;div&gt;&amp;nbsp;Phase 1&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/a/AVvXsEhpGrflIqJoa1bptQK98SdUKaxuXMjfpP8rY6GT8QojJAIbyMIDGvt5gbK-IoL0VUzYugXW5WM3X6Rm_xj0fHPvaFVB2V5WqfkLMDFoq9frbKvzdu4S0xEhE-dDymSysVXTAGJCXjOSUoH46r4hmzF4lW8ovI5v5__kGuCpIXPwPpoL4Dhek0hnLkRxhxdV" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="" data-original-height="872" data-original-width="1472" height="381" src="https://blogger.googleusercontent.com/img/a/AVvXsEhpGrflIqJoa1bptQK98SdUKaxuXMjfpP8rY6GT8QojJAIbyMIDGvt5gbK-IoL0VUzYugXW5WM3X6Rm_xj0fHPvaFVB2V5WqfkLMDFoq9frbKvzdu4S0xEhE-dDymSysVXTAGJCXjOSUoH46r4hmzF4lW8ovI5v5__kGuCpIXPwPpoL4Dhek0hnLkRxhxdV=w640-h381" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;import bpy&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# FLAG WAVE - Y LOCATION ONLY&lt;/div&gt;&lt;div&gt;# Armature : Armature.005&lt;/div&gt;&lt;div&gt;# Bones&amp;nbsp; &amp;nbsp; : Bone.1 - Bone.5&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# Frame 1&amp;nbsp; &amp;nbsp;= Pose A&lt;/div&gt;&lt;div&gt;# Frame 25&amp;nbsp; = Pose B&lt;/div&gt;&lt;div&gt;# Frame 50&amp;nbsp; = Pose A&lt;/div&gt;&lt;div&gt;# Frame 75&amp;nbsp; = Pose B&lt;/div&gt;&lt;div&gt;# Frame 100 = Pose A&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# LOOP: 50 frames per cycle&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;ARMATURE_NAME = "Armature.005"&lt;/div&gt;&lt;div&gt;arm = bpy.data.objects.get(ARMATURE_NAME)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;if arm is None:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; raise Exception(f"Armature '{ARMATURE_NAME}' tidak ditemukan.")&lt;/div&gt;&lt;div&gt;# ------------------------------------------------------------&lt;/div&gt;&lt;div&gt;# POSE A&lt;/div&gt;&lt;div&gt;# Pangkal kecil -&amp;gt; ujung bebas besar&lt;/div&gt;&lt;div&gt;# ------------------------------------------------------------&lt;/div&gt;&lt;div&gt;POSE_A = {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.1":&amp;nbsp; 0.00,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.2":&amp;nbsp; 0.30,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.3": -0.60,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.4":&amp;nbsp; 1.00,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.5": -1.40,&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;# ------------------------------------------------------------&lt;/div&gt;&lt;div&gt;# POSE B&lt;/div&gt;&lt;div&gt;# Fase berlawanan&lt;/div&gt;&lt;div&gt;# ------------------------------------------------------------&lt;/div&gt;&lt;div&gt;POSE_B = {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.1":&amp;nbsp; 0.00,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.2": -0.30,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.3":&amp;nbsp; 0.60,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.4": -1.00,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.5":&amp;nbsp; 1.40,&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;# ------------------------------------------------------------&lt;/div&gt;&lt;div&gt;# KEYFRAME PLAN&lt;/div&gt;&lt;div&gt;# ------------------------------------------------------------&lt;/div&gt;&lt;div&gt;KEYS = {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; 1:&amp;nbsp; &amp;nbsp;POSE_A,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; 25:&amp;nbsp; POSE_B,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; 50:&amp;nbsp; POSE_A,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; 75:&amp;nbsp; POSE_B,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; 100: POSE_A,&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# APPLY KEYFRAMES&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;for frame, pose in KEYS.items():&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; bpy.context.scene.frame_set(frame)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; for bone_name, y_value in pose.items():&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; bone = arm.pose.bones.get(bone_name)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if bone is None:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(f"WARNING: {bone_name} tidak ditemukan")&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; continue&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Hanya ubah Y&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; bone.location.y = y_value&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Keyframe hanya Y Location&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; bone.keyframe_insert(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; data_path="location",&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; index=1,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; frame=frame&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# INTERPOLATION&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# Bezier supaya gerakan tidak linear/kaku&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;if arm.animation_data and arm.animation_data.action:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; action = arm.animation_data.action&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; for fcurve in action.fcurves:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if 'location' in fcurve.data_path and fcurve.array_index == 1:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for kp in fcurve.keyframe_points:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kp.interpolation = 'BEZIER'&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Handle otomatis untuk transisi smooth&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kp.handle_left_type = 'AUTO_CLAMPED'&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kp.handle_right_type = 'AUTO_CLAMPED'&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ------------------------------------------------------------&lt;/div&gt;&lt;div&gt;# Timeline&lt;/div&gt;&lt;div&gt;# ------------------------------------------------------------&lt;/div&gt;&lt;div&gt;bpy.context.scene.frame_start = 1&lt;/div&gt;&lt;div&gt;bpy.context.scene.frame_end = 100&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;bpy.context.scene.frame_set(1)&lt;/div&gt;&lt;div&gt;print("==========================================")&lt;/div&gt;&lt;div&gt;print("FLAG WAVE CREATED")&lt;/div&gt;&lt;div&gt;print("Frame 1&amp;nbsp; &amp;nbsp;: Pose A")&lt;/div&gt;&lt;div&gt;print("Frame 25&amp;nbsp; : Pose B")&lt;/div&gt;&lt;div&gt;print("Frame 50&amp;nbsp; : Pose A")&lt;/div&gt;&lt;div&gt;print("Frame 75&amp;nbsp; : Pose B")&lt;/div&gt;&lt;div&gt;print("Frame 100 : Pose A")&lt;/div&gt;&lt;div&gt;print("Loop&amp;nbsp; &amp;nbsp; &amp;nbsp; : 50 frames")&lt;/div&gt;&lt;div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhZu4NYyOENM2bkHIwzn3H7m93LbUhWL40ey9xLq86vXZ5aDmPzbtT6wmOPMhZf-zT9_-XJl2kNGUiguWOLLKdUn51Z1PdFjcIASrNIofULFvOaz8bfFW9EFUu1AMiMQeZHzdmw9QPbgYvNjAjTV39Dqo1u3zGZKSCJh38WHLAOsVdvyydrtqH1fOTo5rh/s426/bonePreview.gif" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="240" data-original-width="426" height="360" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhhZu4NYyOENM2bkHIwzn3H7m93LbUhWL40ey9xLq86vXZ5aDmPzbtT6wmOPMhZf-zT9_-XJl2kNGUiguWOLLKdUn51Z1PdFjcIASrNIofULFvOaz8bfFW9EFUu1AMiMQeZHzdmw9QPbgYvNjAjTV39Dqo1u3zGZKSCJh38WHLAOsVdvyydrtqH1fOTo5rh/w640-h360/bonePreview.gif" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;print("==========================================")&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;---------------------------&lt;br /&gt;&lt;div&gt;import bpy&lt;/div&gt;&lt;div&gt;import math&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# TRAVELING FLAG WAVE - EXPLICIT 1..100 LOOP&lt;/div&gt;&lt;div&gt;# Armature : Armature.005&lt;/div&gt;&lt;div&gt;# Bones&amp;nbsp; &amp;nbsp; : Bone.1 - Bone.5&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# Keyframes only:&lt;/div&gt;&lt;div&gt;# 1, 25, 50, 75, 100&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# Frame 1 == Frame 100&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;ARMATURE_NAME = "Armature.005"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;START_FRAME = 1&lt;/div&gt;&lt;div&gt;END_FRAME&amp;nbsp; &amp;nbsp;= 100&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;KEY_FRAMES = [1, 25, 50, 75, 100]&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;arm = bpy.data.objects.get(ARMATURE_NAME)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;if arm is None:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; raise Exception(f"{ARMATURE_NAME} tidak ditemukan")&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# AMPLITUDE&lt;/div&gt;&lt;div&gt;# makin jauh dari pangkal -&amp;gt; makin besar&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;AMPLITUDE = {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.1": 0.20,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.2": 0.80,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.3": 1.10,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.4": 1.50,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.5": 1.90,&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# PHASE OFFSET&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# dinyatakan sebagai bagian dari 1 siklus&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# Bone.1 -&amp;gt; pangkal&lt;/div&gt;&lt;div&gt;# Bone.5 -&amp;gt; ujung&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;PHASE_OFFSET = {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.1": 0.00,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.2": 0.08,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.3": 0.16,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.4": 0.24,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.5": 0.32,&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# START PHASE&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;START_PHASE = math.pi / 2.0&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# DELETE OLD Y LOCATION KEYFRAMES&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;if arm.animation_data and arm.animation_data.action:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; action = arm.animation_data.action&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; for fc in list(action.fcurves):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if fc.array_index != 1:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; continue&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for bone_name in AMPLITUDE:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; target_path = f'pose.bones["{bone_name}"].location'&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if fc.data_path == target_path:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; action.fcurves.remove(fc)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; break&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# CREATE KEYFRAMES&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;for frame in KEY_FRAMES:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; bpy.context.scene.frame_set(frame)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # Normalized loop position:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; #&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # frame 1&amp;nbsp; &amp;nbsp;= 0.0&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # frame 100 = 1.0&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; #&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; loop_t = (&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (frame - START_FRAME)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; / (END_FRAME - START_FRAME)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; for bone_name, amp in AMPLITUDE.items():&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; bone = arm.pose.bones.get(bone_name)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if bone is None:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(f"WARNING: {bone_name} tidak ditemukan")&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; continue&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; phase_offset = PHASE_OFFSET[bone_name]&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; phase = (&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 2.0 * math.pi * (loop_t - phase_offset)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; + START_PHASE&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; y = amp * math.sin(phase)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; bone.location.y = y&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; bone.keyframe_insert(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; data_path="location",&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; index=1,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; frame=frame&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f"Frame {frame:3d} | "&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f"{bone_name:7s} | "&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f"Y = {y:+.3f}"&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# FORCE FRAME 100 = FRAME 1 EXACTLY&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# Floating-point theoretically already gives same result,&lt;/div&gt;&lt;div&gt;# but we explicitly copy it for perfect loop.&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;for bone_name in AMPLITUDE:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; bone = arm.pose.bones.get(bone_name)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; if bone is None:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; continue&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # Read frame 1&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; bpy.context.scene.frame_set(START_FRAME)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; y_start = bone.location.y&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # Set exact same value at frame 100&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; bpy.context.scene.frame_set(END_FRAME)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; bone.location.y = y_start&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; bone.keyframe_insert(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; data_path="location",&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; index=1,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; frame=END_FRAME&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# INTERPOLATION&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;if arm.animation_data and arm.animation_data.action:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; action = arm.animation_data.action&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; for fc in action.fcurves:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if fc.array_index != 1:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; continue&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for bone_name in AMPLITUDE:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; target_path = f'pose.bones["{bone_name}"].location'&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if fc.data_path == target_path:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for kp in fc.keyframe_points:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kp.interpolation = 'BEZIER'&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kp.handle_left_type = 'AUTO'&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kp.handle_right_type = 'AUTO'&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# TIMELINE&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;bpy.context.scene.frame_start = START_FRAME&lt;/div&gt;&lt;div&gt;bpy.context.scene.frame_end = END_FRAME&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;bpy.context.scene.frame_set(START_FRAME)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;print("")&lt;/div&gt;&lt;div&gt;print("==========================================")&lt;/div&gt;&lt;div&gt;print("TRAVELING FLAG WAVE DONE")&lt;/div&gt;&lt;div&gt;print("")&lt;/div&gt;&lt;div&gt;print("LOOP:")&lt;/div&gt;&lt;div&gt;print("Frame 1 == Frame 100")&lt;/div&gt;&lt;div&gt;print("")&lt;/div&gt;&lt;div&gt;print("KEYFRAMES:")&lt;/div&gt;&lt;div&gt;print("1, 25, 50, 75, 100")&lt;/div&gt;&lt;div&gt;print("")&lt;/div&gt;&lt;div&gt;print("AMPLITUDE:")&lt;/div&gt;&lt;div&gt;for bone_name, value in AMPLITUDE.items():&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; print(f"{bone_name}: {value}")&lt;/div&gt;&lt;div&gt;print("")&lt;/div&gt;&lt;div&gt;print("==========================================")&lt;/div&gt;&lt;/div&gt;&lt;br /&gt;&lt;/div&gt;</content><link href="http://it-tude.blogspot.com/feeds/1133832483464789672/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/1133832483464789672" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/1133832483464789672" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/1133832483464789672" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/08/basic-bone-for-flag-animation.html" rel="alternate" title="Basic Bone For Flag Animation" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/a/AVvXsEhpGrflIqJoa1bptQK98SdUKaxuXMjfpP8rY6GT8QojJAIbyMIDGvt5gbK-IoL0VUzYugXW5WM3X6Rm_xj0fHPvaFVB2V5WqfkLMDFoq9frbKvzdu4S0xEhE-dDymSysVXTAGJCXjOSUoH46r4hmzF4lW8ovI5v5__kGuCpIXPwPpoL4Dhek0hnLkRxhxdV=s72-w640-h381-c" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-3553825767079419254</id><published>2026-08-18T15:17:08.758-07:00</published><updated>2026-08-18T15:22:39.170-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="animasi"/><category scheme="http://www.blogger.com/atom/ns#" term="Blender"/><category scheme="http://www.blogger.com/atom/ns#" term="python"/><title type="text">traveling wave</title><content type="html">&lt;div style="text-align: left;"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/a/AVvXsEhlAnVnzmbk_Sdy7C6u8CgHPjmvVRfYFvSzS7NcmvcB_bejFcQbt860saWhjDa3rVV4bCKJO0Oms-Vc7uyh9GhnaSR1lnHDC4LOQdEhedXDXOEaqf5kpK0eLOOUJQq3kqdJPEaLqk7X38xqXbhvsBVxNL1O3pizZKRhjaYwt0Jdir88MQJ0HWiaaOTWjRh7" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="" data-original-height="810" data-original-width="743" height="240" src="https://blogger.googleusercontent.com/img/a/AVvXsEhlAnVnzmbk_Sdy7C6u8CgHPjmvVRfYFvSzS7NcmvcB_bejFcQbt860saWhjDa3rVV4bCKJO0Oms-Vc7uyh9GhnaSR1lnHDC4LOQdEhedXDXOEaqf5kpK0eLOOUJQq3kqdJPEaLqk7X38xqXbhvsBVxNL1O3pizZKRhjaYwt0Jdir88MQJ0HWiaaOTWjRh7" width="220" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;import bpy&lt;br /&gt;import math&lt;br /&gt;# ============================================================&lt;br /&gt;# 4-BONE TRAVELING Y WAVE&lt;br /&gt;#&lt;br /&gt;# Mix konsep:&lt;br /&gt;# A = setiap bone naik/turun&lt;br /&gt;# B = wave merambat sepanjang deretan bone&lt;br /&gt;#&lt;br /&gt;# ONLY LOCATION Y&lt;br /&gt;#&lt;br /&gt;# Frame 1&amp;nbsp; &amp;nbsp;= current Y pose&lt;br /&gt;# Frame 201 = exact frame 1&lt;br /&gt;#&lt;br /&gt;# Playback / render:&lt;br /&gt;# 1 - 200&lt;br /&gt;# ============================================================&lt;br /&gt;ARMATURE_NAME = "Armature.003"&lt;br /&gt;START_FRAME = 1&lt;br /&gt;PERIOD = 200&lt;br /&gt;LOOP_FRAME = START_FRAME + PERIOD&lt;br /&gt;&lt;br /&gt;# ============================================================&lt;br /&gt;# BONE ORDER SECARA SPASIAL&lt;br /&gt;#&lt;br /&gt;# Sumber/ujung kanan -&amp;gt; menuju ujung lainnya.&lt;br /&gt;#&lt;br /&gt;# Kalau nanti arah rambat terbalik,&lt;br /&gt;# cukup reverse list ini atau ubah WAVE_DIRECTION.&lt;br /&gt;# ============================================================&lt;br /&gt;BONES = [&lt;br /&gt;&amp;nbsp; &amp;nbsp; "Bone.005",&lt;br /&gt;&amp;nbsp; &amp;nbsp; "Bone.004",&lt;br /&gt;&amp;nbsp; &amp;nbsp; "Bone.002",&lt;br /&gt;&amp;nbsp; &amp;nbsp; "Bone001",&lt;br /&gt;]&lt;br /&gt;&lt;br /&gt;# ============================================================&lt;br /&gt;# CONTROLS&lt;br /&gt;# ============================================================&lt;br /&gt;# Besar displacement wave dari bentuk awal.&lt;br /&gt;AMPLITUDE = 1.45&lt;br /&gt;# Berapa banyak gelombang sepanjang 4 bone.&lt;br /&gt;#&lt;br /&gt;# 1.0 = satu cycle penuh dari bone pertama ke terakhir.&lt;br /&gt;# 0.75 = wave lebih panjang / elegan.&lt;br /&gt;# 1.25 = wave lebih rapat.&lt;br /&gt;SPATIAL_CYCLES = 0.85&lt;br /&gt;# +1 / -1 membalik arah rambat.&lt;br /&gt;WAVE_DIRECTION = 1.0&lt;br /&gt;&lt;br /&gt;# ============================================================&lt;br /&gt;# SPARSE SAMPLE FRAMES&lt;br /&gt;#&lt;br /&gt;# Bukan tiap frame.&lt;br /&gt;# Masih gampang diedit manual.&lt;br /&gt;# ============================================================&lt;br /&gt;KEY_FRAMES = [&lt;br /&gt;&amp;nbsp; &amp;nbsp; 1,&lt;br /&gt;&amp;nbsp; &amp;nbsp; 13,&lt;br /&gt;&amp;nbsp; &amp;nbsp; 26,&lt;br /&gt;&amp;nbsp; &amp;nbsp; 38,&lt;br /&gt;&amp;nbsp; &amp;nbsp; 51,&lt;br /&gt;&amp;nbsp; &amp;nbsp; 63,&lt;br /&gt;&amp;nbsp; &amp;nbsp; 76,&lt;br /&gt;&amp;nbsp; &amp;nbsp; 88,&lt;br /&gt;&amp;nbsp; &amp;nbsp; 101,&lt;br /&gt;&amp;nbsp; &amp;nbsp; 113,&lt;br /&gt;&amp;nbsp; &amp;nbsp; 126,&lt;br /&gt;&amp;nbsp; &amp;nbsp; 138,&lt;br /&gt;&amp;nbsp; &amp;nbsp; 151,&lt;br /&gt;&amp;nbsp; &amp;nbsp; 163,&lt;br /&gt;&amp;nbsp; &amp;nbsp; 176,&lt;br /&gt;&amp;nbsp; &amp;nbsp; 188,&lt;br /&gt;&amp;nbsp; &amp;nbsp; 201,&lt;br /&gt;]&lt;br /&gt;&lt;br /&gt;# ============================================================&lt;br /&gt;# GET ARMATURE&lt;br /&gt;# ============================================================&lt;br /&gt;arm = bpy.data.objects.get(ARMATURE_NAME)&lt;br /&gt;if arm is None:&lt;br /&gt;&amp;nbsp; &amp;nbsp; raise Exception(&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f"Armature '{ARMATURE_NAME}' tidak ditemukan."&lt;br /&gt;&amp;nbsp; &amp;nbsp; )&lt;br /&gt;if arm.type != 'ARMATURE':&lt;br /&gt;&amp;nbsp; &amp;nbsp; raise Exception(&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f"'{ARMATURE_NAME}' bukan Armature."&lt;br /&gt;&amp;nbsp; &amp;nbsp; )&lt;br /&gt;scene = bpy.context.scene&lt;br /&gt;&lt;br /&gt;# ============================================================&lt;br /&gt;# FRAME 1 = BASE SHAPE&lt;br /&gt;# ============================================================&lt;br /&gt;scene.frame_set(START_FRAME)&lt;br /&gt;BASE_Y = {}&lt;br /&gt;for name in BONES:&lt;br /&gt;&amp;nbsp; &amp;nbsp; pb = arm.pose.bones.get(name)&lt;br /&gt;&amp;nbsp; &amp;nbsp; if pb is None:&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; raise Exception(&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f"Bone '{name}' tidak ditemukan."&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;br /&gt;&amp;nbsp; &amp;nbsp; BASE_Y[name] = pb.location.y&lt;br /&gt;&lt;br /&gt;# ============================================================&lt;br /&gt;# BACKUP ACTION&lt;br /&gt;# ============================================================&lt;br /&gt;if arm.animation_data and arm.animation_data.action:&lt;br /&gt;&amp;nbsp; &amp;nbsp; old = arm.animation_data.action&lt;br /&gt;&amp;nbsp; &amp;nbsp; backup = old.copy()&lt;br /&gt;&amp;nbsp; &amp;nbsp; backup.name = old.name + "_BEFORE_TRAVEL_WAVE"&lt;br /&gt;&amp;nbsp; &amp;nbsp; backup.use_fake_user = True&lt;br /&gt;&lt;br /&gt;# ============================================================&lt;br /&gt;# CLEAR OLD ANIMATION&lt;br /&gt;# ============================================================&lt;br /&gt;if arm.animation_data:&lt;br /&gt;&amp;nbsp; &amp;nbsp; arm.animation_data_clear()&lt;br /&gt;&lt;br /&gt;# ============================================================&lt;br /&gt;# SPATIAL POSITION&lt;br /&gt;#&lt;br /&gt;# 4 bones:&lt;br /&gt;#&lt;br /&gt;# 005 = 0.00&lt;br /&gt;# 004 = 0.33&lt;br /&gt;# 002 = 0.67&lt;br /&gt;# 001 = 1.00&lt;br /&gt;# ============================================================&lt;br /&gt;N = len(BONES)&lt;br /&gt;X = {}&lt;br /&gt;for i, name in enumerate(BONES):&lt;br /&gt;&amp;nbsp; &amp;nbsp; X[name] = (&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; i / (N - 1)&lt;br /&gt;&amp;nbsp; &amp;nbsp; )&lt;br /&gt;&lt;br /&gt;# ============================================================&lt;br /&gt;# WAVE FUNCTION&lt;br /&gt;#&lt;br /&gt;# Traveling wave:&lt;br /&gt;#&lt;br /&gt;# sin(kx - wt)&lt;br /&gt;# ============================================================&lt;br /&gt;def wave(name, time_phase):&lt;br /&gt;&amp;nbsp; &amp;nbsp; x = X[name]&lt;br /&gt;&amp;nbsp; &amp;nbsp; spatial_phase = (&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; math.tau&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; * SPATIAL_CYCLES&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; * x&lt;br /&gt;&amp;nbsp; &amp;nbsp; )&lt;br /&gt;&amp;nbsp; &amp;nbsp; return math.sin(&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; spatial_phase&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; WAVE_DIRECTION * time_phase&lt;br /&gt;&amp;nbsp; &amp;nbsp; )&lt;br /&gt;&lt;br /&gt;# ============================================================&lt;br /&gt;# INITIAL WAVE VALUE&lt;br /&gt;#&lt;br /&gt;# Kita kurangi nilai ini dari seluruh animasi.&lt;br /&gt;#&lt;br /&gt;# Hasilnya:&lt;br /&gt;# displacement pada frame 1 = 0.&lt;br /&gt;# ============================================================&lt;br /&gt;INITIAL_WAVE = {}&lt;br /&gt;for name in BONES:&lt;br /&gt;&amp;nbsp; &amp;nbsp; INITIAL_WAVE[name] = wave(&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; name,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 0.0&lt;br /&gt;&amp;nbsp; &amp;nbsp; )&lt;br /&gt;&lt;br /&gt;# ============================================================&lt;br /&gt;# GENERATE&lt;br /&gt;# ============================================================&lt;br /&gt;for frame in KEY_FRAMES:&lt;br /&gt;&amp;nbsp; &amp;nbsp; progress = (&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; frame - START_FRAME&lt;br /&gt;&amp;nbsp; &amp;nbsp; ) / PERIOD&lt;br /&gt;&amp;nbsp; &amp;nbsp; time_phase = (&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; math.tau * progress&lt;br /&gt;&amp;nbsp; &amp;nbsp; )&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; for name in BONES:&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; pb = arm.pose.bones[name]&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # ----------------------------------------------------&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # displacement dari traveling wave&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # ----------------------------------------------------&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; current_wave = wave(&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; name,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; time_phase&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; wave_delta = (&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; current_wave&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; INITIAL_WAVE[name]&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # ----------------------------------------------------&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # final Y&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # ----------------------------------------------------&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; y = (&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; BASE_Y[name]&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; +&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; wave_delta&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; * AMPLITUDE&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # Exact start/end&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if frame == START_FRAME or frame == LOOP_FRAME:&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; y = BASE_Y[name]&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; pb.location.y = y&lt;br /&gt;&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; pb.keyframe_insert(&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; data_path="location",&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; index=1,&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; frame=frame&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;br /&gt;&lt;br /&gt;# ============================================================&lt;br /&gt;# SMOOTH INTERPOLATION&lt;br /&gt;#&lt;br /&gt;# AUTO handles lebih flowy.&lt;br /&gt;#&lt;br /&gt;# Tidak pakai AUTO_CLAMPED karena di sini sedikit curvature&lt;br /&gt;# antar sample justru membantu rasa gelombang.&lt;br /&gt;# ============================================================&lt;br /&gt;if arm.animation_data and arm.animation_data.action:&lt;br /&gt;&amp;nbsp; &amp;nbsp; action = arm.animation_data.action&lt;br /&gt;&amp;nbsp; &amp;nbsp; action.name = "TRAVELING_Y_WAVE"&lt;br /&gt;&amp;nbsp; &amp;nbsp; for fc in action.fcurves:&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for kp in fc.keyframe_points:&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kp.interpolation = 'BEZIER'&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kp.handle_left_type = 'AUTO'&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kp.handle_right_type = 'AUTO'&lt;br /&gt;&lt;br /&gt;# ============================================================&lt;br /&gt;# TIMELINE&lt;br /&gt;# ============================================================&lt;br /&gt;scene.frame_start = 1&lt;br /&gt;scene.frame_end = 200&lt;br /&gt;scene.frame_set(1)&lt;br /&gt;&lt;br /&gt;# ============================================================&lt;br /&gt;# REPORT&lt;br /&gt;# ============================================================&lt;br /&gt;print("")&lt;br /&gt;print("=" * 70)&lt;br /&gt;print("TRAVELING Y WAVE CREATED")&lt;br /&gt;print("=" * 70)&lt;br /&gt;print("")&lt;br /&gt;print("BASE Y:")&lt;br /&gt;for name in BONES:&lt;br /&gt;&amp;nbsp; &amp;nbsp; print(&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f"{name:10s}",&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; round(BASE_Y[name], 4),&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; "| x =",&lt;br /&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; round(X[name], 3)&lt;br /&gt;&amp;nbsp; &amp;nbsp; )&lt;br /&gt;print("")&lt;br /&gt;print("Amplitude&amp;nbsp; &amp;nbsp; &amp;nbsp; :", AMPLITUDE)&lt;br /&gt;print("Spatial cycles :", SPATIAL_CYCLES)&lt;br /&gt;print("Period&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;:", PERIOD)&lt;br /&gt;print("Loop reference :", LOOP_FRAME)&lt;br /&gt;print("")&lt;br /&gt;print("Frame 1&amp;nbsp; &amp;nbsp;= original Y")&lt;br /&gt;print("Frame 201 = original Y exact")&lt;br /&gt;print("")&lt;br /&gt;print("Only Y Location animated.")&lt;br /&gt;print("=" * 70)&lt;br /&gt;-----&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;evently&lt;br /&gt;---&lt;br /&gt;&lt;div&gt;import bpy&lt;/div&gt;&lt;div&gt;import math&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# TRAVELING Y WAVE - EVENT BASED SPARSE KEYS&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# ONLY LOCATION Y&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# Frame 1&amp;nbsp; &amp;nbsp;= current Y&lt;/div&gt;&lt;div&gt;# Frame 201 = current Y lagi&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# Setiap bone hanya dapat key pada:&lt;/div&gt;&lt;div&gt;# START / MAX / CENTER / MIN / CENTER / LOOP&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;ARMATURE_NAME = "Armature.005"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;START_FRAME = 1&lt;/div&gt;&lt;div&gt;PERIOD = 200&lt;/div&gt;&lt;div&gt;LOOP_FRAME = START_FRAME + PERIOD&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;AMPLITUDE = 2.10&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;BONES = [&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.005",&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.004",&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.002",&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone001",&lt;/div&gt;&lt;div&gt;]&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# SPATIAL PHASE&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# Ini yang bikin wave "jalan" dari bone ke bone.&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;SPATIAL_PHASE = {&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.005": math.radians(0),&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.004": math.radians(60),&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone.002": math.radians(120),&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; "Bone001":&amp;nbsp; math.radians(180),&lt;/div&gt;&lt;div&gt;}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# GET ARMATURE&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;arm = bpy.data.objects.get(ARMATURE_NAME)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;if arm is None:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; raise Exception(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f"Armature '{ARMATURE_NAME}' tidak ditemukan."&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;scene = bpy.context.scene&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;scene.frame_set(START_FRAME)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# READ CURRENT Y&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;START_Y = {}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;for name in BONES:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; pb = arm.pose.bones.get(name)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; if pb is None:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; raise Exception(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f"Bone '{name}' tidak ditemukan."&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; START_Y[name] = pb.location.y&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# BACKUP&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;if arm.animation_data and arm.animation_data.action:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; old = arm.animation_data.action&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; backup = old.copy()&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; backup.name = old.name + "_BEFORE_SPARSE_EVENT"&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; backup.use_fake_user = True&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# CLEAR OLD ANIMATION&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;if arm.animation_data:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; arm.animation_data_clear()&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# TIME -&amp;gt; FRAME&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# satu cycle 0..2π = 200 frame&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;def angle_to_frame(angle):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; angle %= math.tau&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; return (&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; START_FRAME&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; +&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (angle / math.tau)&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; * PERIOD&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# CALCULATE PHASE FROM START POSITION&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# Kita ingin:&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# Y(0) = START_Y&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# dengan:&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# Y = A sin(theta + phase)&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# lalu kita tambahkan spatial phase.&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;PHASE = {}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;for name in BONES:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; normalized = max(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; -1.0,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; min(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 1.0,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; START_Y[name] / AMPLITUDE&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; base_phase = math.asin(normalized)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; PHASE[name] = (&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; base_phase&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; + SPATIAL_PHASE[name]&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; ) % math.tau&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# EVENT ANGLES&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# posisi sinus:&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# +MAX&amp;nbsp; &amp;nbsp;= π/2&lt;/div&gt;&lt;div&gt;# CENTER = π&lt;/div&gt;&lt;div&gt;# -MAX&amp;nbsp; &amp;nbsp;= 3π/2&lt;/div&gt;&lt;div&gt;# CENTER = 2π&lt;/div&gt;&lt;div&gt;#&lt;/div&gt;&lt;div&gt;# lalu siklus lanjut.&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;TARGETS = [&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; ("MAX",&amp;nbsp; &amp;nbsp; math.pi / 2,&amp;nbsp; &amp;nbsp; &amp;nbsp; AMPLITUDE),&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; ("CENTER", math.pi,&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; 0.0),&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; ("MIN",&amp;nbsp; &amp;nbsp; 3 * math.pi / 2, -AMPLITUDE),&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; ("CENTER", 2 * math.pi,&amp;nbsp; &amp;nbsp; &amp;nbsp; 0.0),&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; ("MAX",&amp;nbsp; &amp;nbsp; 5 * math.pi / 2,&amp;nbsp; AMPLITUDE),&lt;/div&gt;&lt;div&gt;]&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# BUILD SPARSE KEYS&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;ALL_KEYS = {}&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;for name in BONES:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; phase = PHASE[name]&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; pb = arm.pose.bones[name]&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; keys = []&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # --------------------------------------------------------&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # START&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # --------------------------------------------------------&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; keys.append(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; float(START_FRAME),&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; START_Y[name],&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; "START"&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # --------------------------------------------------------&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # FIND NEXT EVENTS&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # --------------------------------------------------------&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; for label, target_angle, target_y in TARGETS:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; theta = (&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; target_angle&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; - phase&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ) % math.tau&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # kalau persis di start, skip&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if theta &amp;lt; 1e-5:&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; continue&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; frame = angle_to_frame(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; theta&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; # hanya di dalam cycle&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; if (&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; frame &amp;gt; START_FRAME&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; and frame &amp;lt; LOOP_FRAME&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; ):&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; keys.append(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; frame,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; target_y,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; label&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # --------------------------------------------------------&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # LOOP END&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # --------------------------------------------------------&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; keys.append(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; (&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; float(LOOP_FRAME),&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; START_Y[name],&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; "LOOP"&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # --------------------------------------------------------&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # SORT&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # --------------------------------------------------------&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; keys.sort(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; key=lambda x: x[0]&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # ========================================================&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # INSERT KEYS&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; # ========================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; for frame, y, label in keys:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; pb.location.y = y&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; pb.keyframe_insert(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; data_path="location",&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; index=1,&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; frame=frame&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; ALL_KEYS[name] = keys&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# BEZIER SMOOTH&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;if arm.animation_data and arm.animation_data.action:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; action = arm.animation_data.action&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; action.name = "TRAVELING_Y_WAVE_SPARSE"&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; for fc in action.fcurves:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; for kp in fc.keyframe_points:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kp.interpolation = 'BEZIER'&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kp.handle_left_type = 'AUTO_CLAMPED'&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; kp.handle_right_type = 'AUTO_CLAMPED'&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# TIMELINE&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;scene.frame_start = START_FRAME&lt;/div&gt;&lt;div&gt;scene.frame_end&amp;nbsp; &amp;nbsp;= LOOP_FRAME - 1&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;scene.frame_set(START_FRAME)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;# PRINT RESULT&lt;/div&gt;&lt;div&gt;# ============================================================&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;print("")&lt;/div&gt;&lt;div&gt;print("=" * 75)&lt;/div&gt;&lt;div&gt;print("TRAVELING Y WAVE - SPARSE EVENT KEYS")&lt;/div&gt;&lt;div&gt;print("=" * 75)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;for name in BONES:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; print("")&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; print(name)&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; for frame, y, label in ALL_KEYS[name]:&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; print(&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f"&amp;nbsp; {label:7s}"&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f" frame {frame:7.2f}"&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; f"&amp;nbsp; &amp;nbsp;Y = {y: .4f}"&lt;/div&gt;&lt;div&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; )&lt;/div&gt;&lt;div&gt;&lt;br /&gt;&lt;/div&gt;&lt;div&gt;print("")&lt;/div&gt;&lt;div&gt;print("Frame 201 = Frame 1")&lt;/div&gt;&lt;div&gt;print("=" * 75)&lt;/div&gt;&lt;/div&gt;</content><link href="http://it-tude.blogspot.com/feeds/3553825767079419254/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/3553825767079419254" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/3553825767079419254" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/3553825767079419254" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/08/traveling-wave.html" rel="alternate" title="traveling wave" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/a/AVvXsEhlAnVnzmbk_Sdy7C6u8CgHPjmvVRfYFvSzS7NcmvcB_bejFcQbt860saWhjDa3rVV4bCKJO0Oms-Vc7uyh9GhnaSR1lnHDC4LOQdEhedXDXOEaqf5kpK0eLOOUJQq3kqdJPEaLqk7X38xqXbhvsBVxNL1O3pizZKRhjaYwt0Jdir88MQJ0HWiaaOTWjRh7=s72-c" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-145976107131210495</id><published>2026-08-15T12:26:02.033-07:00</published><updated>2026-08-15T12:27:55.844-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Blender"/><category scheme="http://www.blogger.com/atom/ns#" term="Blender Material"/><title type="text">GLOWING EDGE MATERIAL 1</title><content type="html">&lt;h1&gt;Membuat Material Glowing Edge Procedural di Blender&lt;/h1&gt;&lt;p&gt;Pada objek 3D seperti teks, logo, atau emblem, salah satu cara sederhana untuk memberikan kesan lebih premium adalah membuat bagian pinggir objek terlihat lebih terang dibandingkan permukaan utamanya. Efek ini dapat digunakan sebagai dasar &lt;strong&gt;glowing edge&lt;/strong&gt;, terutama jika hasil render nantinya akan dilanjutkan dengan compositing di After Effects.&lt;/p&gt;&lt;p&gt;Pada eksperimen ini, material dibuat menggunakan &lt;strong&gt;satu material procedural&lt;/strong&gt; bernama &lt;strong&gt;&lt;code inline=""&gt;Glowing Edge&lt;/code&gt;&lt;/strong&gt;. Tidak diperlukan material terpisah untuk bagian bevel atau edge objek.&lt;/p&gt;&lt;h2&gt;Konsep Material&lt;/h2&gt;&lt;p&gt;Material menggunakan &lt;strong&gt;Principled BSDF&lt;/strong&gt; sebagai shader utama dengan karakter permukaan metallic berwarna silver.&lt;/p&gt;&lt;p&gt;Efek terang pada pinggir objek dibuat menggunakan nilai &lt;strong&gt;Facing&lt;/strong&gt; dari node &lt;strong&gt;Layer Weight&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Secara sederhana, &lt;code inline=""&gt;Facing&lt;/code&gt; memberikan informasi mengenai orientasi permukaan terhadap kamera. Permukaan yang menghadap langsung ke kamera memiliki nilai berbeda dengan permukaan yang terlihat pada sudut menyamping.&lt;/p&gt;&lt;p&gt;Informasi tersebut kemudian digunakan sebagai mask untuk menentukan bagian mana yang mendapatkan emission.&lt;/p&gt;&lt;p&gt;Alur dasarnya:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-text"&gt;Layer Weight
     │
   Facing
     │
     ▼
 ColorRamp
     │
     ▼
 Multiply
     │
     ▼
Emission Strength
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Dengan metode ini, edge tidak perlu dipisahkan menjadi geometry atau material tersendiri.&lt;/p&gt;&lt;h2&gt;Base Material&lt;/h2&gt;&lt;p&gt;Permukaan utama menggunakan &lt;strong&gt;Principled BSDF&lt;/strong&gt; dengan konfigurasi:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-text"&gt;Base Color : RGB (0.92, 0.92, 0.95)
Metallic   : 1.0
Roughness  : 0.22
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nilai Metallic &lt;code inline=""&gt;1.0&lt;/code&gt; membuat material bereaksi seperti permukaan logam, sementara Roughness &lt;code inline=""&gt;0.22&lt;/code&gt; mempertahankan refleksi yang cukup tajam.&lt;/p&gt;&lt;p&gt;Warna dasar sedikit kebiruan dibandingkan putih murni sehingga memberikan karakter &lt;strong&gt;cold silver&lt;/strong&gt;.&lt;/p&gt;&lt;h2&gt;Membentuk Glowing Edge&lt;/h2&gt;&lt;p&gt;Deteksi edge menggunakan:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-text"&gt;Layer Weight → Facing
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Output tersebut kemudian masuk ke &lt;strong&gt;ColorRamp&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;ColorRamp pada material ini menggunakan nilai:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-text"&gt;White Position : 0.58
Black Position : 0.88
Interpolation  : EASE
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;ColorRamp berfungsi mengontrol seberapa luas area yang dianggap sebagai edge.&lt;/p&gt;&lt;p&gt;Setelah itu hasil mask diperkuat menggunakan Math Node:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-text"&gt;Operation : Multiply
Value     : 3.0
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Output akhirnya dihubungkan ke:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-text"&gt;Principled BSDF → Emission Strength
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Sedangkan warna emission menggunakan warm white:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-text"&gt;Emission Color

R : 1.00
G : 0.82
B : 0.55
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Perpaduan antara &lt;strong&gt;cold silver surface&lt;/strong&gt; dan &lt;strong&gt;warm edge highlight&lt;/strong&gt; memberikan sedikit pemisahan warna sehingga pinggiran objek terlihat lebih hidup.&lt;/p&gt;&lt;h2&gt;Menambahkan Micro Surface&lt;/h2&gt;&lt;p&gt;Supaya material tidak terlihat terlalu sempurna atau flat, ditambahkan detail permukaan menggunakan &lt;strong&gt;Noise Texture&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Konfigurasinya:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-text"&gt;Noise Texture

Dimensions : 3D
Scale      : 220
Detail     : 2.0
Roughness  : 0.5
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Noise tersebut tidak digunakan untuk mengubah warna material, tetapi diteruskan ke node &lt;strong&gt;Bump&lt;/strong&gt;:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-text"&gt;Bump

Strength : 0.025
Distance : 0.008
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Alurnya:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-text"&gt;Texture Coordinate
        │
        ▼
  Noise Texture
        │
        ▼
      Bump
        │
        ▼
Principled BSDF
      Normal
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Nilainya sengaja dibuat kecil karena tujuannya hanya memberikan &lt;strong&gt;micro surface variation&lt;/strong&gt;, bukan membuat permukaan terlihat kasar secara berlebihan.&lt;/p&gt;&lt;h2&gt;Struktur Material&lt;/h2&gt;&lt;p&gt;Secara keseluruhan material mempunyai dua sistem procedural.&lt;/p&gt;&lt;p&gt;&lt;strong&gt;Edge system:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-text"&gt;Layer Weight
      ↓
    Facing
      ↓
  ColorRamp
      ↓
Multiply × 3
      ↓
Emission Strength
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;&lt;strong&gt;Surface detail system:&lt;/strong&gt;&lt;/p&gt;&lt;pre&gt;&lt;code class="language-text"&gt;Texture Coordinate
      ↓
Noise Texture
      ↓
     Bump
      ↓
Principled BSDF Normal
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Keduanya kemudian bekerja pada satu &lt;strong&gt;Principled BSDF&lt;/strong&gt; yang diteruskan ke Material Output.&lt;/p&gt;&lt;h2&gt;Karakter Efek&lt;/h2&gt;&lt;p&gt;Hal penting dari teknik ini adalah glowing edge bersifat &lt;strong&gt;view-dependent&lt;/strong&gt;.&lt;/p&gt;&lt;p&gt;Artinya, posisi highlight ditentukan oleh hubungan antara &lt;strong&gt;surface normal dan sudut pandang kamera&lt;/strong&gt;. Ketika kamera atau objek bergerak, distribusi edge highlight juga dapat berubah.&lt;/p&gt;&lt;p&gt;Karena itu teknik ini lebih tepat disebut sebagai:&lt;/p&gt;&lt;p&gt;&lt;strong&gt;View-Dependent Glowing Edge / Fresnel-Like Edge Highlight&lt;/strong&gt;&lt;/p&gt;&lt;p&gt;dan bukan directional top-edge lighting.&lt;/p&gt;&lt;p&gt;Jika yang dibutuhkan adalah highlight yang selalu muncul pada sisi atas objek terlepas dari posisi kamera, pendekatannya berbeda. Dalam kasus tersebut, surface normal dapat dibandingkan dengan arah lokal atau world-space tertentu.&lt;/p&gt;&lt;h2&gt;Workflow Blender → After Effects&lt;/h2&gt;&lt;p&gt;Emission pada Blender tidak harus dibuat sangat kuat.&lt;/p&gt;&lt;p&gt;Dalam workflow compositing, Blender cukup menghasilkan &lt;strong&gt;hot edge&lt;/strong&gt; yang jelas dan memiliki luminance lebih tinggi daripada permukaan utama.&lt;/p&gt;&lt;p&gt;Contohnya:&lt;/p&gt;&lt;pre&gt;&lt;code class="language-text"&gt;Blender
   ↓
Metallic Surface
   +
Bright / Hot Edge
   ↓
Render
   ↓
After Effects
   ↓
Glow / Bloom
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;Dengan pendekatan tersebut, bentuk dan posisi highlight tetap berasal dari geometry 3D, sementara karakter glow seperti radius, intensity, threshold, dan falloff dapat dikontrol lebih fleksibel saat compositing di After Effects.&lt;/p&gt;&lt;h2&gt;Kesimpulan&lt;/h2&gt;&lt;p&gt;Material &lt;strong&gt;Glowing Edge&lt;/strong&gt; menggunakan satu material procedural untuk menghasilkan permukaan metallic sekaligus edge highlight tanpa perlu memisahkan bevel menjadi material lain.&lt;/p&gt;&lt;p&gt;Kombinasi &lt;strong&gt;Layer Weight, ColorRamp, Emission, Noise Texture, dan Bump&lt;/strong&gt; membuat material tetap sederhana tetapi cukup fleksibel untuk digunakan pada teks 3D, logo, emblem, maupun objek hard-surface.&lt;/p&gt;&lt;p&gt;Teknik ini juga cocok untuk workflow motion graphics karena Blender dapat difokuskan untuk menghasilkan &lt;strong&gt;surface dan highlight information&lt;/strong&gt;, sementara efek glow akhir disempurnakan pada tahap compositing.&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;&amp;nbsp;import bpy&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;# GLOWING EDGE MATERIAL 1&lt;/p&gt;&lt;p&gt;# Blender 4.x / 5.x&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;MAT_NAME = "Glowing Edge"&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ------------------------------------------------------------&lt;/p&gt;&lt;p&gt;# Get active object&lt;/p&gt;&lt;p&gt;# ------------------------------------------------------------&lt;/p&gt;&lt;p&gt;obj = bpy.context.active_object&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;if obj is None:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; raise Exception("Tidak ada object aktif. Pilih object dulu.")&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ------------------------------------------------------------&lt;/p&gt;&lt;p&gt;# Create / reuse material&lt;/p&gt;&lt;p&gt;# ------------------------------------------------------------&lt;/p&gt;&lt;p&gt;mat = bpy.data.materials.get(MAT_NAME)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;if mat is None:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; mat = bpy.data.materials.new(name=MAT_NAME)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;mat.use_nodes = True&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;nodes = mat.node_tree.nodes&lt;/p&gt;&lt;p&gt;links = mat.node_tree.links&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Clear existing nodes&lt;/p&gt;&lt;p&gt;nodes.clear()&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;# NODES&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Material Output&lt;/p&gt;&lt;p&gt;output = nodes.new("ShaderNodeOutputMaterial")&lt;/p&gt;&lt;p&gt;output.name = "Material Output"&lt;/p&gt;&lt;p&gt;output.label = "Material Output"&lt;/p&gt;&lt;p&gt;output.location = (850, 0)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Principled BSDF&lt;/p&gt;&lt;p&gt;bsdf = nodes.new("ShaderNodeBsdfPrincipled")&lt;/p&gt;&lt;p&gt;bsdf.name = "Principled BSDF"&lt;/p&gt;&lt;p&gt;bsdf.label = "Glowing Edge Surface"&lt;/p&gt;&lt;p&gt;bsdf.location = (560, 0)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Base metallic surface&lt;/p&gt;&lt;p&gt;bsdf.inputs["Base Color"].default_value = (0.92, 0.92, 0.95, 1.0)&lt;/p&gt;&lt;p&gt;bsdf.inputs["Metallic"].default_value = 1.0&lt;/p&gt;&lt;p&gt;bsdf.inputs["Roughness"].default_value = 0.22&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Slight warm emission color&lt;/p&gt;&lt;p&gt;if "Emission Color" in bsdf.inputs:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; bsdf.inputs["Emission Color"].default_value = (1.0, 0.82, 0.55, 1.0)&lt;/p&gt;&lt;p&gt;else:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; bsdf.inputs["Emission"].default_value = (1.0, 0.82, 0.55, 1.0)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ------------------------------------------------------------&lt;/p&gt;&lt;p&gt;# Layer Weight&lt;/p&gt;&lt;p&gt;# ------------------------------------------------------------&lt;/p&gt;&lt;p&gt;layer = nodes.new("ShaderNodeLayerWeight")&lt;/p&gt;&lt;p&gt;layer.name = "Layer Weight"&lt;/p&gt;&lt;p&gt;layer.label = "Edge Detection"&lt;/p&gt;&lt;p&gt;layer.location = (-500, 120)&lt;/p&gt;&lt;p&gt;layer.inputs["Blend"].default_value = 0.5&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ------------------------------------------------------------&lt;/p&gt;&lt;p&gt;# ColorRamp&lt;/p&gt;&lt;p&gt;# ------------------------------------------------------------&lt;/p&gt;&lt;p&gt;ramp = nodes.new("ShaderNodeValToRGB")&lt;/p&gt;&lt;p&gt;ramp.name = "Edge Ramp"&lt;/p&gt;&lt;p&gt;ramp.label = "Glowing Edge Control"&lt;/p&gt;&lt;p&gt;ramp.location = (-260, 120)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Remove default positions and tune edge&lt;/p&gt;&lt;p&gt;cr = ramp.color_ramp&lt;/p&gt;&lt;p&gt;cr.elements[0].position = 0.58&lt;/p&gt;&lt;p&gt;cr.elements[0].color = (1.0, 1.0, 1.0, 1.0)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;cr.elements[1].position = 0.88&lt;/p&gt;&lt;p&gt;cr.elements[1].color = (0.0, 0.0, 0.0, 1.0)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;cr.interpolation = 'EASE'&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ------------------------------------------------------------&lt;/p&gt;&lt;p&gt;# Multiply edge intensity&lt;/p&gt;&lt;p&gt;# ------------------------------------------------------------&lt;/p&gt;&lt;p&gt;multiply = nodes.new("ShaderNodeMath")&lt;/p&gt;&lt;p&gt;multiply.name = "Glow Strength"&lt;/p&gt;&lt;p&gt;multiply.label = "Glow Strength"&lt;/p&gt;&lt;p&gt;multiply.operation = 'MULTIPLY'&lt;/p&gt;&lt;p&gt;multiply.location = (30, 120)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;multiply.inputs[1].default_value = 3.0&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ------------------------------------------------------------&lt;/p&gt;&lt;p&gt;# Noise texture for subtle surface variation&lt;/p&gt;&lt;p&gt;# ------------------------------------------------------------&lt;/p&gt;&lt;p&gt;texcoord = nodes.new("ShaderNodeTexCoord")&lt;/p&gt;&lt;p&gt;texcoord.name = "Texture Coordinate"&lt;/p&gt;&lt;p&gt;texcoord.location = (-520, -220)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;noise = nodes.new("ShaderNodeTexNoise")&lt;/p&gt;&lt;p&gt;noise.name = "Surface Noise"&lt;/p&gt;&lt;p&gt;noise.location = (-280, -220)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;noise.noise_dimensions = '3D'&lt;/p&gt;&lt;p&gt;noise.inputs["Scale"].default_value = 220.0&lt;/p&gt;&lt;p&gt;noise.inputs["Detail"].default_value = 2.0&lt;/p&gt;&lt;p&gt;noise.inputs["Roughness"].default_value = 0.5&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ------------------------------------------------------------&lt;/p&gt;&lt;p&gt;# Bump&lt;/p&gt;&lt;p&gt;# ------------------------------------------------------------&lt;/p&gt;&lt;p&gt;bump = nodes.new("ShaderNodeBump")&lt;/p&gt;&lt;p&gt;bump.name = "Micro Bump"&lt;/p&gt;&lt;p&gt;bump.location = (250, -220)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;bump.inputs["Strength"].default_value = 0.025&lt;/p&gt;&lt;p&gt;bump.inputs["Distance"].default_value = 0.008&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;# LINKS&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;links.new(layer.outputs["Facing"], ramp.inputs["Fac"])&lt;/p&gt;&lt;p&gt;links.new(ramp.outputs["Color"], multiply.inputs[0])&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;if "Emission Strength" in bsdf.inputs:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; links.new(multiply.outputs["Value"], bsdf.inputs["Emission Strength"])&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;links.new(texcoord.outputs["Generated"], noise.inputs["Vector"])&lt;/p&gt;&lt;p&gt;links.new(noise.outputs["Fac"], bump.inputs["Height"])&lt;/p&gt;&lt;p&gt;links.new(bump.outputs["Normal"], bsdf.inputs["Normal"])&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;links.new(bsdf.outputs["BSDF"], output.inputs["Surface"])&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;# ASSIGN TO OBJECT&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;if len(obj.data.materials) == 0:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; obj.data.materials.append(mat)&lt;/p&gt;&lt;p&gt;else:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; obj.data.materials[0] = mat&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;print(f"Material '{MAT_NAME}' berhasil dibuat dan dipasang ke '{obj.name}'.")&lt;/p&gt;</content><link href="http://it-tude.blogspot.com/feeds/145976107131210495/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/145976107131210495" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/145976107131210495" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/145976107131210495" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/08/glowing-edge-material-1.html" rel="alternate" title="GLOWING EDGE MATERIAL 1" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-1737967424847117556</id><published>2026-08-15T12:25:26.197-07:00</published><updated>2026-08-15T12:32:22.586-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Blender Material"/><title type="text">Glowing Edge Material 2</title><content type="html">&lt;p&gt;&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/a/AVvXsEghykDJhhdK7C6nFzIy1SIGr3MwF-VN5ew2oUdV2wO7lV0r1N3EzlzoUjZVcyDXlzIVbIooUJVHsWRTlXXivELveQuaa_fTPNN9E8M8nyjTB_TzfYW18eCBL9Fm1rSo6XrNAoZ7sRTR6oeQlszj4VUyYVcLm5TgzJk9ANs6jjCU5DugTflrMFaugQ64c06G" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="" data-original-height="147" data-original-width="607" height="126" src="https://blogger.googleusercontent.com/img/a/AVvXsEghykDJhhdK7C6nFzIy1SIGr3MwF-VN5ew2oUdV2wO7lV0r1N3EzlzoUjZVcyDXlzIVbIooUJVHsWRTlXXivELveQuaa_fTPNN9E8M8nyjTB_TzfYW18eCBL9Fm1rSo6XrNAoZ7sRTR6oeQlszj4VUyYVcLm5TgzJk9ANs6jjCU5DugTflrMFaugQ64c06G=w525-h126" width="525" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;import bpy&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;# GLOWING EDGE - TOP EDGE MATERIAL&lt;/p&gt;&lt;p&gt;# Brightens ONLY upward-facing bevel / top edges&lt;/p&gt;&lt;p&gt;# Blender 4.x / 5.x&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;MAT_NAME = "Glowing Edge"&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;obj = bpy.context.active_object&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;if obj is None:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; raise RuntimeError("choose the object first : @rtxid")&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ------------------------------------------------------------&lt;/p&gt;&lt;p&gt;# MATERIAL&lt;/p&gt;&lt;p&gt;# ------------------------------------------------------------&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;mat = bpy.data.materials.get(MAT_NAME)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;if mat is None:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; mat = bpy.data.materials.new(MAT_NAME)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;mat.use_nodes = True&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;nodes = mat.node_tree.nodes&lt;/p&gt;&lt;p&gt;links = mat.node_tree.links&lt;/p&gt;&lt;p&gt;nodes.clear()&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;# OUTPUT&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;output = nodes.new("ShaderNodeOutputMaterial")&lt;/p&gt;&lt;p&gt;output.location = (900, 0)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;bsdf = nodes.new("ShaderNodeBsdfPrincipled")&lt;/p&gt;&lt;p&gt;bsdf.location = (620, 0)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;links.new(bsdf.outputs["BSDF"], output.inputs["Surface"])&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Metallic text&lt;/p&gt;&lt;p&gt;bsdf.inputs["Metallic"].default_value = 1.0&lt;/p&gt;&lt;p&gt;bsdf.inputs["Roughness"].default_value = 0.24&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;# BASE COLOR&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;base_color = nodes.new("ShaderNodeRGB")&lt;/p&gt;&lt;p&gt;base_color.label = "BASE SILVER"&lt;/p&gt;&lt;p&gt;base_color.location = (-100, 180)&lt;/p&gt;&lt;p&gt;base_color.outputs[0].default_value = (&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 0.72,&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 0.72,&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 0.74,&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 1.0&lt;/p&gt;&lt;p&gt;)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# HOT TOP COLOR&lt;/p&gt;&lt;p&gt;hot_color = nodes.new("ShaderNodeRGB")&lt;/p&gt;&lt;p&gt;hot_color.label = "HOT TOP EDGE"&lt;/p&gt;&lt;p&gt;hot_color.location = (-100, 300)&lt;/p&gt;&lt;p&gt;hot_color.outputs[0].default_value = (&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 1.0,&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 0.97,&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 0.88,&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; 1.0&lt;/p&gt;&lt;p&gt;)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;# DETECT UPWARD-FACING NORMAL&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;geometry = nodes.new("ShaderNodeNewGeometry")&lt;/p&gt;&lt;p&gt;geometry.label = "SURFACE NORMAL"&lt;/p&gt;&lt;p&gt;geometry.location = (-900, 400)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;transform = nodes.new("ShaderNodeVectorTransform")&lt;/p&gt;&lt;p&gt;transform.label = "WORLD → OBJECT"&lt;/p&gt;&lt;p&gt;transform.location = (-680, 400)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;transform.vector_type = 'NORMAL'&lt;/p&gt;&lt;p&gt;transform.convert_from = 'WORLD'&lt;/p&gt;&lt;p&gt;transform.convert_to = 'OBJECT'&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;separate = nodes.new("ShaderNodeSeparateXYZ")&lt;/p&gt;&lt;p&gt;separate.label = "LOCAL XYZ"&lt;/p&gt;&lt;p&gt;separate.location = (-470, 400)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;links.new(&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; geometry.outputs["Normal"],&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; transform.inputs["Vector"]&lt;/p&gt;&lt;p&gt;)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;links.new(&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; transform.outputs["Vector"],&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; separate.inputs["Vector"]&lt;/p&gt;&lt;p&gt;)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;# TOP EDGE MASK&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;ramp = nodes.new("ShaderNodeValToRGB")&lt;/p&gt;&lt;p&gt;ramp.label = "TOP EDGE WIDTH"&lt;/p&gt;&lt;p&gt;ramp.location = (-250, 430)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;cr = ramp.color_ramp&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Surfaces not facing upward = black&lt;/p&gt;&lt;p&gt;cr.elements[0].position = 0.20&lt;/p&gt;&lt;p&gt;cr.elements[0].color = (0, 0, 0, 1)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# Strong upward-facing surfaces = white&lt;/p&gt;&lt;p&gt;cr.elements[1].position = 0.72&lt;/p&gt;&lt;p&gt;cr.elements[1].color = (1, 1, 1, 1)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;cr.interpolation = 'EASE'&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# IMPORTANT:&lt;/p&gt;&lt;p&gt;# Default Blender text:&lt;/p&gt;&lt;p&gt;# X = horizontal&lt;/p&gt;&lt;p&gt;# Y = vertical&lt;/p&gt;&lt;p&gt;# Z = extrusion/depth&lt;/p&gt;&lt;p&gt;#&lt;/p&gt;&lt;p&gt;# Therefore LOCAL +Y detects the TOP of letters.&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;links.new(&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; separate.outputs["Y"],&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; ramp.inputs["Fac"]&lt;/p&gt;&lt;p&gt;)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;# MIX BASE + HOT EDGE&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;mix = nodes.new("ShaderNodeMixRGB")&lt;/p&gt;&lt;p&gt;mix.label = "TOP EDGE BRIGHTNESS"&lt;/p&gt;&lt;p&gt;mix.blend_type = 'MIX'&lt;/p&gt;&lt;p&gt;mix.location = (180, 220)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;links.new(ramp.outputs["Color"], mix.inputs[0])&lt;/p&gt;&lt;p&gt;links.new(base_color.outputs["Color"], mix.inputs[1])&lt;/p&gt;&lt;p&gt;links.new(hot_color.outputs["Color"], mix.inputs[2])&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;links.new(&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; mix.outputs["Color"],&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; bsdf.inputs["Base Color"]&lt;/p&gt;&lt;p&gt;)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;# SMALL EMISSION FOR AE GLOW SOURCE&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;if "Emission Color" in bsdf.inputs:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; links.new(&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; mix.outputs["Color"],&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; bsdf.inputs["Emission Color"]&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; )&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;if "Emission Strength" in bsdf.inputs:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; bsdf.inputs["Emission Strength"].default_value = 0.25&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;# MICRO SURFACE&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;texcoord = nodes.new("ShaderNodeTexCoord")&lt;/p&gt;&lt;p&gt;texcoord.location = (-850, -180)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;noise = nodes.new("ShaderNodeTexNoise")&lt;/p&gt;&lt;p&gt;noise.location = (-600, -180)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;noise.noise_dimensions = '3D'&lt;/p&gt;&lt;p&gt;noise.inputs["Scale"].default_value = 220.0&lt;/p&gt;&lt;p&gt;noise.inputs["Detail"].default_value = 2.0&lt;/p&gt;&lt;p&gt;noise.inputs["Roughness"].default_value = 0.5&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;bump = nodes.new("ShaderNodeBump")&lt;/p&gt;&lt;p&gt;bump.location = (330, -170)&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;bump.inputs["Strength"].default_value = 0.020&lt;/p&gt;&lt;p&gt;bump.inputs["Distance"].default_value = 0.006&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;links.new(texcoord.outputs["Generated"], noise.inputs["Vector"])&lt;/p&gt;&lt;p&gt;links.new(noise.outputs["Fac"], bump.inputs["Height"])&lt;/p&gt;&lt;p&gt;links.new(bump.outputs["Normal"], bsdf.inputs["Normal"])&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;# ASSIGN MATERIAL&lt;/p&gt;&lt;p&gt;# ============================================================&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;if len(obj.data.materials) == 0:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; obj.data.materials.append(mat)&lt;/p&gt;&lt;p&gt;else:&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; obj.data.materials[0] = mat&lt;/p&gt;&lt;p&gt;&lt;br /&gt;&lt;/p&gt;&lt;p&gt;print(&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; f"'{MAT_NAME}' has made for object '{obj.name}'. "&lt;/p&gt;&lt;p&gt;&amp;nbsp; &amp;nbsp; "Top-facing bevel now are more glowing."&lt;/p&gt;&lt;p&gt;)&lt;/p&gt;</content><link href="http://it-tude.blogspot.com/feeds/1737967424847117556/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/1737967424847117556" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/1737967424847117556" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/1737967424847117556" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/08/glowing-edge-material-2.html" rel="alternate" title="Glowing Edge Material 2" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/a/AVvXsEghykDJhhdK7C6nFzIy1SIGr3MwF-VN5ew2oUdV2wO7lV0r1N3EzlzoUjZVcyDXlzIVbIooUJVHsWRTlXXivELveQuaa_fTPNN9E8M8nyjTB_TzfYW18eCBL9Fm1rSo6XrNAoZ7sRTR6oeQlszj4VUyYVcLm5TgzJk9ANs6jjCU5DugTflrMFaugQ64c06G=s72-w525-h126-c" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-7531117151216805693</id><published>2026-06-07T11:12:46.245-07:00</published><updated>2026-06-07T11:12:46.245-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Android"/><category scheme="http://www.blogger.com/atom/ns#" term="IT-Tude Notes"/><category scheme="http://www.blogger.com/atom/ns#" term="Kotlin"/><category scheme="http://www.blogger.com/atom/ns#" term="Mobile App"/><title type="text">Android Bukan Path</title><content type="html">&lt;p&gt;Saat baru pindah dari HTML dan CSS ke Android, bagian yang sering bikin bingung adalah cara memanggil gambar, warna, dan nama aplikasi. Di web, kita biasa menulis path langsung seperti /image/logo.png. Di Android, cara berpikirnya berbeda. Android memakai sistem resource.&lt;/p&gt;
&lt;p&gt;Resource adalah file yang diletakkan di folder app/src/main/res. Setelah file masuk ke sana, Android mengenal file itu lewat nama resource, bukan lewat path lengkap.&lt;/p&gt;
&lt;h2&gt;Judul aplikasi&lt;/h2&gt;
&lt;p&gt;Nama aplikasi biasanya disimpan di file app/src/main/res/values/strings.xml. Contohnya:&lt;/p&gt;
&lt;p&gt;string name app_name berisi IT-Tude Self Attendance.&lt;/p&gt;
&lt;p&gt;Di AndroidManifest.xml, nama itu dipanggil lewat android:label=&amp;quot;@string/app_name&amp;quot;. Artinya aplikasi mengambil teks dari resource string bernama app_name.&lt;/p&gt;
&lt;p&gt;Kalau ingin mengganti judul aplikasi yang muncul di launcher, ubah nilai app_name di strings.xml.&lt;/p&gt;
&lt;h2&gt;Gambar bukan dipanggil seperti HTML&lt;/h2&gt;
&lt;p&gt;Kalau di web kita menulis src=&amp;quot;/image/logo.png&amp;quot;, di Android kita menaruh gambar ke folder resource. Misalnya file logo_baru.png diletakkan di app/src/main/res/drawable-nodpi.&lt;/p&gt;
&lt;p&gt;Cara memanggilnya bukan dengan path folder, tetapi dengan nama resource:&lt;/p&gt;
&lt;p&gt;@drawable/logo_baru&lt;/p&gt;
&lt;p&gt;Walaupun file berada di drawable-nodpi, referensinya tetap @drawable/nama_file.&lt;/p&gt;
&lt;h2&gt;Folder yang sering dipakai&lt;/h2&gt;
&lt;p&gt;Folder values dipakai untuk data kecil seperti string dan warna. strings.xml dipanggil dengan @string/nama. colors.xml dipanggil dengan @color/nama.&lt;/p&gt;
&lt;p&gt;Folder drawable dipakai untuk gambar, vector, shape, atau background XML.&lt;/p&gt;
&lt;p&gt;Folder drawable-nodpi dipakai untuk gambar PNG yang tidak ingin otomatis diskalakan berdasarkan density layar.&lt;/p&gt;
&lt;p&gt;Folder mipmap dipakai untuk launcher icon aplikasi. Android punya beberapa ukuran seperti mipmap-mdpi, mipmap-hdpi, mipmap-xhdpi, mipmap-xxhdpi, dan mipmap-xxxhdpi. Sistem akan memilih ukuran yang cocok untuk perangkat.&lt;/p&gt;
&lt;h2&gt;Adaptive icon&lt;/h2&gt;
&lt;p&gt;Android versi baru memakai adaptive icon. File utamanya biasanya ada di app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml.&lt;/p&gt;
&lt;p&gt;Isinya memanggil background dan foreground. Contohnya, background putih bisa dipanggil dari @color/ic_launcher_background_white. Logo depan bisa dipanggil dari @drawable/ic_launcher_foreground_logo.&lt;/p&gt;
&lt;p&gt;Jadi adaptive icon tidak harus satu gambar utuh. Ia bisa terdiri dari background dan foreground.&lt;/p&gt;
&lt;h2&gt;Rumus cepat&lt;/h2&gt;
&lt;p&gt;Jika file ada di values/strings.xml, panggil dengan @string/nama.&lt;/p&gt;
&lt;p&gt;Jika warna ada di values/colors.xml, panggil dengan @color/nama.&lt;/p&gt;
&lt;p&gt;Jika gambar ada di drawable atau drawable-nodpi, panggil dengan @drawable/nama_file.&lt;/p&gt;
&lt;p&gt;Jika launcher icon ada di mipmap, panggil dengan @mipmap/nama_file.&lt;/p&gt;
&lt;h2&gt;Cara aman ganti logo sendiri&lt;/h2&gt;
&lt;p&gt;Untuk mengganti logo aplikasi, siapkan PNG yang bersih. Letakkan di app/src/main/res/drawable-nodpi. Contohnya logo_it_tude.png.&lt;/p&gt;
&lt;p&gt;Lalu di adaptive icon, panggil:&lt;/p&gt;
&lt;p&gt;@drawable/logo_it_tude&lt;/p&gt;
&lt;p&gt;Untuk launcher icon lama, siapkan juga file di folder mipmap dengan nama ic_launcher.webp dan ic_launcher_round.webp pada setiap density.&lt;/p&gt;
&lt;p&gt;Kesimpulannya sederhana: Android bukan membaca path seperti HTML. Android membaca resource. Setelah paham pola @string, @color, @drawable, dan @mipmap, mengganti judul aplikasi atau logo akan terasa jauh lebih masuk akal.&lt;/p&gt;</content><link href="http://it-tude.blogspot.com/feeds/7531117151216805693/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/7531117151216805693" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/7531117151216805693" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/7531117151216805693" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/06/android-bukan-path.html" rel="alternate" title="Android Bukan Path" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-7484700372301251393</id><published>2026-05-31T18:24:55.491-07:00</published><updated>2026-05-31T18:24:55.491-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="chatbot"/><category scheme="http://www.blogger.com/atom/ns#" term="software"/><category scheme="http://www.blogger.com/atom/ns#" term="tutorial"/><category scheme="http://www.blogger.com/atom/ns#" term="workflow"/><title type="text">Bagaimana Chatbot IT-Tude Bekerja di Website</title><content type="html">&lt;p&gt;Chatbot IT-Tude bekerja sebagai asisten virtual yang menerima pertanyaan dari pengunjung, lalu mencoba memberi jawaban atau arahan yang paling relevan berdasarkan konteks layanan yang tersedia.&lt;/p&gt;
&lt;p&gt;Secara sederhana, alurnya dimulai saat pengunjung mengetik pertanyaan di widget chat pada website. Setelah itu, chatbot membaca isi pertanyaan dan mencoba mengenali maksud utamanya. Jika pertanyaannya masih umum, chatbot akan mengarahkan ke kategori layanan yang paling sesuai. Jika pertanyaannya lebih spesifik, chatbot akan mencoba memberi jawaban yang lebih fokus berdasarkan knowledge yang sudah disiapkan.&lt;/p&gt;
&lt;p&gt;Dalam alur ini, chatbot tidak selalu harus menjawab semua hal secara panjang. Untuk pertanyaan tertentu, chatbot cukup memberi penjelasan ringkas lalu menawarkan langkah berikutnya. Misalnya, pengunjung bisa diarahkan untuk melihat jalur software, memahami layanan chatbot, atau melanjutkan ke admin melalui WhatsApp jika pembahasannya sudah masuk ke kebutuhan yang lebih detail.&lt;/p&gt;
&lt;p&gt;Pendekatan seperti ini membuat chatbot lebih efisien. Pengunjung tetap merasa dibantu, tetapi alur percakapan tidak menjadi terlalu berat. Chatbot juga bisa diposisikan sebagai alat bantu awal sebelum komunikasi masuk ke tahap diskusi yang lebih serius.&lt;/p&gt;
&lt;p&gt;Dengan model kerja seperti ini, chatbot IT-Tude bisa mendukung website agar lebih interaktif, lebih informatif, dan lebih siap menangani pertanyaan awal dari calon pengguna layanan.&lt;/p&gt;</content><link href="http://it-tude.blogspot.com/feeds/7484700372301251393/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/7484700372301251393" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/7484700372301251393" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/7484700372301251393" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/05/bagaimana-chatbot-it-tude-bekerja-di_0107869225.html" rel="alternate" title="Bagaimana Chatbot IT-Tude Bekerja di Website" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-185979010151022222</id><published>2026-05-31T18:23:48.575-07:00</published><updated>2026-05-31T18:23:48.575-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="benefits"/><category scheme="http://www.blogger.com/atom/ns#" term="chatbot"/><category scheme="http://www.blogger.com/atom/ns#" term="software"/><category scheme="http://www.blogger.com/atom/ns#" term="umkm"/><title type="text">Manfaat Chatbot IT-Tude untuk Website UMKM</title><content type="html">&lt;p&gt;Bagi website UMKM, kehadiran chatbot bisa menjadi nilai tambah yang cukup penting, terutama ketika pengunjung membutuhkan jawaban cepat sebelum memutuskan untuk bertanya lebih lanjut atau melakukan kontak.&lt;/p&gt;
&lt;p&gt;Chatbot IT-Tude dapat membantu website UMKM menjawab pertanyaan berulang yang biasanya sering muncul, seperti layanan apa saja yang tersedia, produk mana yang paling sesuai, atau bagaimana cara memulai diskusi kebutuhan. Dengan begitu, pengunjung tidak harus menunggu balasan manual untuk mendapatkan gambaran awal.&lt;/p&gt;
&lt;p&gt;Selain itu, chatbot juga membantu menjaga alur komunikasi tetap ringan. Pengunjung bisa langsung mendapat arahan ke jalur yang paling relevan tanpa harus membaca seluruh halaman terlebih dahulu. Ini penting untuk website usaha yang ingin terlihat lebih aktif, lebih responsif, dan lebih mudah diakses.&lt;/p&gt;
&lt;p&gt;Manfaat lainnya adalah chatbot bisa membantu menyaring kebutuhan awal pengunjung. Dari pertanyaan singkat, chatbot dapat mengarahkan apakah kebutuhan mereka lebih cocok ke software, digital art, atau layanan lain yang sedang disiapkan. Setelah itu, chatbot bisa melanjutkan dengan ajakan ke email atau WhatsApp admin untuk pembahasan yang lebih detail.&lt;/p&gt;
&lt;p&gt;Untuk UMKM, pendekatan seperti ini membantu website terasa lebih hidup. Bukan hanya tampil sebagai halaman informasi, tetapi juga sebagai pintu masuk komunikasi yang lebih praktis untuk calon pelanggan.&lt;/p&gt;</content><link href="http://it-tude.blogspot.com/feeds/185979010151022222/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/185979010151022222" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/185979010151022222" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/185979010151022222" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/05/manfaat-chatbot-it-tude-untuk-website_0567754670.html" rel="alternate" title="Manfaat Chatbot IT-Tude untuk Website UMKM" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-3018291418614579913</id><published>2026-05-31T18:23:46.431-07:00</published><updated>2026-05-31T18:23:46.431-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="chatbot"/><category scheme="http://www.blogger.com/atom/ns#" term="lead-capture"/><category scheme="http://www.blogger.com/atom/ns#" term="overview"/><category scheme="http://www.blogger.com/atom/ns#" term="software"/><title type="text">Chatbot IT-Tude untuk Menjawab, Mengarahkan, dan Menangkap Prospek</title><content type="html">&lt;p&gt;Chatbot IT-Tude dirancang bukan hanya untuk menjawab pertanyaan, tetapi juga untuk membantu pengunjung memahami layanan yang tersedia dengan lebih cepat dan lebih terarah.&lt;/p&gt;
&lt;p&gt;Dalam praktiknya, chatbot ini punya tiga fungsi utama. Pertama, sebagai alat untuk menjawab pertanyaan awal seputar layanan IT-Tude. Kedua, sebagai pengarah agar pengunjung bisa masuk ke jalur layanan yang paling relevan, seperti software, digital art, atau mechanical electrical. Ketiga, sebagai alat bantu menangkap prospek awal sebelum pengunjung diarahkan ke admin atau penawaran lanjutan.&lt;/p&gt;
&lt;p&gt;Pendekatan ini membuat chatbot tidak terasa seperti FAQ statis. Chatbot bisa diposisikan sebagai asisten virtual yang membantu menjembatani kebutuhan awal pengunjung dengan solusi yang memang sedang mereka cari.&lt;/p&gt;
&lt;p&gt;Bagi bisnis atau website yang ingin terlihat lebih responsif, chatbot seperti ini dapat membantu memberi kesan bahwa pengunjung tidak dibiarkan mencari informasi sendirian. Bahkan ketika data yang dibutuhkan belum lengkap, chatbot tetap bisa membantu mengarahkan ke langkah berikutnya, seperti meninggalkan email atau melanjutkan ke WhatsApp admin.&lt;/p&gt;
&lt;p&gt;Dengan pola ini, chatbot IT-Tude tidak hanya berfungsi sebagai penjawab otomatis, tetapi juga sebagai bagian dari pengalaman layanan yang lebih rapi dan lebih siap dipakai untuk kebutuhan digital yang terus berkembang.&lt;/p&gt;</content><link href="http://it-tude.blogspot.com/feeds/3018291418614579913/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/3018291418614579913" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/3018291418614579913" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/3018291418614579913" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/05/chatbot-it-tude-untuk-menjawab_050620965.html" rel="alternate" title="Chatbot IT-Tude untuk Menjawab, Mengarahkan, dan Menangkap Prospek" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-384498400247440100</id><published>2026-05-31T18:23:22.273-07:00</published><updated>2026-05-31T18:23:22.273-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="chatbot"/><category scheme="http://www.blogger.com/atom/ns#" term="software"/><category scheme="http://www.blogger.com/atom/ns#" term="tutorial"/><category scheme="http://www.blogger.com/atom/ns#" term="workflow"/><title type="text">Bagaimana Chatbot IT-Tude Bekerja di Website</title><content type="html">&lt;p&gt;Chatbot IT-Tude bekerja sebagai asisten virtual yang menerima pertanyaan dari pengunjung, lalu mencoba memberi jawaban atau arahan yang paling relevan berdasarkan konteks layanan yang tersedia.&lt;/p&gt;
&lt;p&gt;Secara sederhana, alurnya dimulai saat pengunjung mengetik pertanyaan di widget chat pada website. Setelah itu, chatbot membaca isi pertanyaan dan mencoba mengenali maksud utamanya. Jika pertanyaannya masih umum, chatbot akan mengarahkan ke kategori layanan yang paling sesuai. Jika pertanyaannya lebih spesifik, chatbot akan mencoba memberi jawaban yang lebih fokus berdasarkan knowledge yang sudah disiapkan.&lt;/p&gt;
&lt;p&gt;Dalam alur ini, chatbot tidak selalu harus menjawab semua hal secara panjang. Untuk pertanyaan tertentu, chatbot cukup memberi penjelasan ringkas lalu menawarkan langkah berikutnya. Misalnya, pengunjung bisa diarahkan untuk melihat jalur software, memahami layanan chatbot, atau melanjutkan ke admin melalui WhatsApp jika pembahasannya sudah masuk ke kebutuhan yang lebih detail.&lt;/p&gt;
&lt;p&gt;Pendekatan seperti ini membuat chatbot lebih efisien. Pengunjung tetap merasa dibantu, tetapi alur percakapan tidak menjadi terlalu berat. Chatbot juga bisa diposisikan sebagai alat bantu awal sebelum komunikasi masuk ke tahap diskusi yang lebih serius.&lt;/p&gt;
&lt;p&gt;Dengan model kerja seperti ini, chatbot IT-Tude bisa mendukung website agar lebih interaktif, lebih informatif, dan lebih siap menangani pertanyaan awal dari calon pengguna layanan.&lt;/p&gt;</content><link href="http://it-tude.blogspot.com/feeds/384498400247440100/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/384498400247440100" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/384498400247440100" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/384498400247440100" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/05/bagaimana-chatbot-it-tude-bekerja-di.html" rel="alternate" title="Bagaimana Chatbot IT-Tude Bekerja di Website" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-7783423514365351570</id><published>2026-05-31T18:23:20.072-07:00</published><updated>2026-05-31T18:23:20.072-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="benefits"/><category scheme="http://www.blogger.com/atom/ns#" term="chatbot"/><category scheme="http://www.blogger.com/atom/ns#" term="software"/><category scheme="http://www.blogger.com/atom/ns#" term="umkm"/><title type="text">Manfaat Chatbot IT-Tude untuk Website UMKM</title><content type="html">&lt;p&gt;Bagi website UMKM, kehadiran chatbot bisa menjadi nilai tambah yang cukup penting, terutama ketika pengunjung membutuhkan jawaban cepat sebelum memutuskan untuk bertanya lebih lanjut atau melakukan kontak.&lt;/p&gt;
&lt;p&gt;Chatbot IT-Tude dapat membantu website UMKM menjawab pertanyaan berulang yang biasanya sering muncul, seperti layanan apa saja yang tersedia, produk mana yang paling sesuai, atau bagaimana cara memulai diskusi kebutuhan. Dengan begitu, pengunjung tidak harus menunggu balasan manual untuk mendapatkan gambaran awal.&lt;/p&gt;
&lt;p&gt;Selain itu, chatbot juga membantu menjaga alur komunikasi tetap ringan. Pengunjung bisa langsung mendapat arahan ke jalur yang paling relevan tanpa harus membaca seluruh halaman terlebih dahulu. Ini penting untuk website usaha yang ingin terlihat lebih aktif, lebih responsif, dan lebih mudah diakses.&lt;/p&gt;
&lt;p&gt;Manfaat lainnya adalah chatbot bisa membantu menyaring kebutuhan awal pengunjung. Dari pertanyaan singkat, chatbot dapat mengarahkan apakah kebutuhan mereka lebih cocok ke software, digital art, atau layanan lain yang sedang disiapkan. Setelah itu, chatbot bisa melanjutkan dengan ajakan ke email atau WhatsApp admin untuk pembahasan yang lebih detail.&lt;/p&gt;
&lt;p&gt;Untuk UMKM, pendekatan seperti ini membantu website terasa lebih hidup. Bukan hanya tampil sebagai halaman informasi, tetapi juga sebagai pintu masuk komunikasi yang lebih praktis untuk calon pelanggan.&lt;/p&gt;</content><link href="http://it-tude.blogspot.com/feeds/7783423514365351570/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/7783423514365351570" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/7783423514365351570" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/7783423514365351570" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/05/manfaat-chatbot-it-tude-untuk-website.html" rel="alternate" title="Manfaat Chatbot IT-Tude untuk Website UMKM" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-172182883476728943</id><published>2026-05-31T18:23:17.715-07:00</published><updated>2026-05-31T18:23:17.715-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="chatbot"/><category scheme="http://www.blogger.com/atom/ns#" term="lead-capture"/><category scheme="http://www.blogger.com/atom/ns#" term="overview"/><category scheme="http://www.blogger.com/atom/ns#" term="software"/><title type="text">Chatbot IT-Tude untuk Menjawab, Mengarahkan, dan Menangkap Prospek</title><content type="html">&lt;p&gt;Chatbot IT-Tude dirancang bukan hanya untuk menjawab pertanyaan, tetapi juga untuk membantu pengunjung memahami layanan yang tersedia dengan lebih cepat dan lebih terarah.&lt;/p&gt;
&lt;p&gt;Dalam praktiknya, chatbot ini punya tiga fungsi utama. Pertama, sebagai alat untuk menjawab pertanyaan awal seputar layanan IT-Tude. Kedua, sebagai pengarah agar pengunjung bisa masuk ke jalur layanan yang paling relevan, seperti software, digital art, atau mechanical electrical. Ketiga, sebagai alat bantu menangkap prospek awal sebelum pengunjung diarahkan ke admin atau penawaran lanjutan.&lt;/p&gt;
&lt;p&gt;Pendekatan ini membuat chatbot tidak terasa seperti FAQ statis. Chatbot bisa diposisikan sebagai asisten virtual yang membantu menjembatani kebutuhan awal pengunjung dengan solusi yang memang sedang mereka cari.&lt;/p&gt;
&lt;p&gt;Bagi bisnis atau website yang ingin terlihat lebih responsif, chatbot seperti ini dapat membantu memberi kesan bahwa pengunjung tidak dibiarkan mencari informasi sendirian. Bahkan ketika data yang dibutuhkan belum lengkap, chatbot tetap bisa membantu mengarahkan ke langkah berikutnya, seperti meninggalkan email atau melanjutkan ke WhatsApp admin.&lt;/p&gt;
&lt;p&gt;Dengan pola ini, chatbot IT-Tude tidak hanya berfungsi sebagai penjawab otomatis, tetapi juga sebagai bagian dari pengalaman layanan yang lebih rapi dan lebih siap dipakai untuk kebutuhan digital yang terus berkembang.&lt;/p&gt;</content><link href="http://it-tude.blogspot.com/feeds/172182883476728943/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/172182883476728943" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/172182883476728943" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/172182883476728943" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/05/chatbot-it-tude-untuk-menjawab.html" rel="alternate" title="Chatbot IT-Tude untuk Menjawab, Mengarahkan, dan Menangkap Prospek" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-7864825074962540687</id><published>2026-05-10T04:49:00.000-07:00</published><updated>2026-05-26T04:55:51.093-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Artificial Intelligence"/><category scheme="http://www.blogger.com/atom/ns#" term="Artikel"/><title type="text">Jangan Geer, Pas Pake AI Sebenernya Kita Lagi Jadi Gurunya!</title><content type="html">&lt;p&gt;&amp;nbsp;Halo gaes! Pernah mikir gak, pas kita lagi asyik &lt;i data-index-in-node="49" data-path-to-node="3"&gt;chatting&lt;/i&gt; bareng AI—entah minta dibikinin caption, nanya resep, atau benerin &lt;i data-index-in-node="125" data-path-to-node="3"&gt;codingan&lt;/i&gt;—hubungannya itu gak cuma satu arah? Kita gak cuma pake teknologi, tapi &lt;b data-index-in-node="205" data-path-to-node="3"&gt;kita lagi ngajarin mereka.&lt;br /&gt;&lt;/b&gt;&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;b data-index-in-node="205" data-path-to-node="3"&gt;&lt;a href="https://blogger.googleusercontent.com/img/a/AVvXsEj-5l_75KdVR7--iGorgNab7ggmpZdfexQWrtuMYUrVe-T0G2C8qtKQfslsE3qcaK5jCnLoXk_UlB3XFU58Hy-A4BOtRfCL6IPH2RkyzHYcu6vPGUrzRs15GbUWV-7vMHoMT6B1jxrxgDN8850GOJtWl1so6i9G_sNbKCc1SGOEx8wWevBGmnbTZKnlNzhr" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img data-original-height="559" data-original-width="1024" height="350" src="https://blogger.googleusercontent.com/img/a/AVvXsEj-5l_75KdVR7--iGorgNab7ggmpZdfexQWrtuMYUrVe-T0G2C8qtKQfslsE3qcaK5jCnLoXk_UlB3XFU58Hy-A4BOtRfCL6IPH2RkyzHYcu6vPGUrzRs15GbUWV-7vMHoMT6B1jxrxgDN8850GOJtWl1so6i9G_sNbKCc1SGOEx8wWevBGmnbTZKnlNzhr=w640-h350" width="640" /&gt;&lt;/a&gt;&lt;/b&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p data-path-to-node="4"&gt;Setiap kali kita ngoreksi jawabannya, nyuruh ubah gaya bahasa, atau ngajak bercanda, AI langsung mencatat polanya. Miliaran interaksi kita tiap hari adalah bahan bakar yang bikin AI makin pinter meniru cara manusia berpikir. Jadi, secara gak langsung, kita semua adalah mentor sukarela mereka.&lt;/p&gt;&lt;h3 data-path-to-node="5"&gt;Tapi, Ada Satu Hal yang Gak Bakal Bisa Mereka Tiru...&lt;/h3&gt;&lt;p data-path-to-node="6"&gt;Meskipun AI makin pinter karena belajar dari kita, ada satu benteng pertahanan manusia yang gak bakal bisa mereka jebol: &lt;b data-index-in-node="121" data-path-to-node="6"&gt;Kreativitas dan Rasa.&lt;/b&gt;&lt;/p&gt;&lt;p data-path-to-node="7"&gt;AI itu cuma jago menghubungkan titik-titik data yang &lt;i data-index-in-node="53" data-path-to-node="7"&gt;udah ada&lt;/i&gt;. Mereka bisa bikin puisi indah atau gambar keren karena mereka milih dari jutaan data yang pernah dibuat manusia. Tapi mereka gak punya "percikan" emosi, intuisi, pengalaman hidup, atau keresahan batin yang melahirkan sebuah ide baru.&lt;/p&gt;&lt;p data-path-to-node="8"&gt;Kreativitas manusia itu lahir dari rasa patah hati, kopi yang tumpah di pagi hari, atau lamunan random pas lagi mandi. Itu adalah &lt;i data-index-in-node="130" data-path-to-node="8"&gt;human spark&lt;/i&gt;—keberanian untuk bikin sesuatu yang belum pernah ada polanya di dunia. Dan itu gak akan bisa ditularkan ke mesin berbentuk baris kode.&lt;/p&gt;&lt;h3 data-path-to-node="9"&gt;&lt;i data-index-in-node="0" data-path-to-node="9"&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/a/AVvXsEir7QlDeHpRIPJTinqGRGFIG50hgaOIQQ1Lp_VfOwcNg5zT2Hr2aOChNOIOLVktloB8osrZYD-ygK7j5VM1PR4efl7hoD34ZdLFAjBTkbh47j2J91F22nUKrxoWC7e4lhRCDZYar1yEKayI6ZhFcAQTe6CaBYwUq-V30xmqSO0e3VTfdsUrXp6b4okWSsjW" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="" data-original-height="173" data-original-width="661" height="84" src="https://blogger.googleusercontent.com/img/a/AVvXsEir7QlDeHpRIPJTinqGRGFIG50hgaOIQQ1Lp_VfOwcNg5zT2Hr2aOChNOIOLVktloB8osrZYD-ygK7j5VM1PR4efl7hoD34ZdLFAjBTkbh47j2J91F22nUKrxoWC7e4lhRCDZYar1yEKayI6ZhFcAQTe6CaBYwUq-V30xmqSO0e3VTfdsUrXp6b4okWSsjW" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;br /&gt;Closing Thought&lt;/i&gt;&lt;/h3&gt;&lt;p data-path-to-node="10"&gt;AI bisa meniru gaya kita, tapi mereka gak akan bisa punya jiwa kita. Kita adalah gurunya, dan pencipta aslinya.&lt;/p&gt;&lt;p data-path-to-node="11"&gt;Yuk, lebih bijak ngasih "makan" AI kita dengan interaksi yang positif, dan jangan pernah minder, karena kreativitasmu gak akan pernah bisa digantikan oleh algoritma secanggih apa pun.&lt;/p&gt;&lt;p data-path-to-node="12"&gt;Gimana menurut kalian? Yuk, ngobrol di kolom komentar!&lt;/p&gt;</content><link href="http://it-tude.blogspot.com/feeds/7864825074962540687/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/7864825074962540687" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/7864825074962540687" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/7864825074962540687" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/05/jangan-geer-pas-pake-ai-sebenernya-kita.html" rel="alternate" title="Jangan Geer, Pas Pake AI Sebenernya Kita Lagi Jadi Gurunya!" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/a/AVvXsEj-5l_75KdVR7--iGorgNab7ggmpZdfexQWrtuMYUrVe-T0G2C8qtKQfslsE3qcaK5jCnLoXk_UlB3XFU58Hy-A4BOtRfCL6IPH2RkyzHYcu6vPGUrzRs15GbUWV-7vMHoMT6B1jxrxgDN8850GOJtWl1so6i9G_sNbKCc1SGOEx8wWevBGmnbTZKnlNzhr=s72-w640-h350-c" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-6557682053205245275</id><published>2026-04-23T00:12:00.000-07:00</published><updated>2026-04-23T00:12:51.969-07:00</updated><title type="text">Belajar Dasar AI: Cara AI “Noise” - "Denoise"</title><content type="html">&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/a/AVvXsEg6JfYl7pqD0aj_kLM1rtNeOup3mPPlRre234Qj65iiVsWbNVkX0V7_st_-4544EZE_jDc9d7e2qlP-5gvSjyc3a8STkOXehbgSr1Zdkvx4hDah5eWYEsVZDqTMpvNeK6eSP0l46MRA9SQVnQ_02pOTHu7VTaYz-i-On60Mh_V8uBvOdWMh7dQQ1u6rUv4n" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img alt="" data-original-height="963" data-original-width="1842" height="334" src="https://blogger.googleusercontent.com/img/a/AVvXsEg6JfYl7pqD0aj_kLM1rtNeOup3mPPlRre234Qj65iiVsWbNVkX0V7_st_-4544EZE_jDc9d7e2qlP-5gvSjyc3a8STkOXehbgSr1Zdkvx4hDah5eWYEsVZDqTMpvNeK6eSP0l46MRA9SQVnQ_02pOTHu7VTaYz-i-On60Mh_V8uBvOdWMh7dQQ1u6rUv4n=w640-h334" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;p data-end="289" data-start="197"&gt;Lagi belajar AI, aku nemu konsep yang menurutku cukup menarik dan agak “unik” cara kerjanya.&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;
&lt;p data-end="305" data-start="291"&gt;Bayangin gini…&lt;/p&gt;
&lt;p data-end="496" data-start="307"&gt;AI itu bukan langsung bikin gambar dari kosong secara instan.&lt;br data-end="371" data-start="368" /&gt;
Tapi dia justru mulai dari sesuatu yang &lt;strong data-end="434" data-start="411"&gt;acak banget (noise)&lt;/strong&gt;, lalu pelan-pelan “dibersihin” sampai jadi gambar yang jelas.&lt;/p&gt;
&lt;hr data-end="501" data-start="498" /&gt;
&lt;h3 data-end="547" data-section-id="y271k2" data-start="503"&gt;&#128313; Step 1 — Tambah Noise (Ngacak Gambar)&lt;/h3&gt;
&lt;p data-end="654" data-start="549"&gt;Di awal, AI akan mengambil gambar normal… lalu ditambahin &lt;strong data-end="632" data-start="607"&gt;noise (gangguan acak)&lt;/strong&gt; sedikit demi sedikit.&lt;/p&gt;
&lt;ul data-end="770" data-start="656"&gt;
&lt;li data-end="691" data-section-id="285no7" data-start="656"&gt;
Awalnya masih kelihatan bentuknya
&lt;/li&gt;
&lt;li data-end="714" data-section-id="gga6zw" data-start="692"&gt;
Lama-lama makin blur
&lt;/li&gt;
&lt;li data-end="770" data-section-id="p6ksnb" data-start="715"&gt;
Sampai akhirnya jadi kayak TV rusak / pixel random &#128517;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end="791" data-start="772"&gt;Proses ini disebut:&lt;/p&gt;
&lt;blockquote data-end="825" data-start="792"&gt;
&lt;p data-end="825" data-start="794"&gt;&lt;strong data-end="825" data-start="794"&gt;Diffusion (forward process)&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-end="830" data-start="827" /&gt;
&lt;h3 data-end="877" data-section-id="etnb0e" data-start="832"&gt;&#128313; Step 2 — Denoise (Balikin Jadi Gambar)&lt;/h3&gt;
&lt;p data-end="910" data-start="879"&gt;Nah, bagian menariknya di sini…&lt;/p&gt;
&lt;p data-end="953" data-start="912"&gt;AI dilatih untuk &lt;strong data-end="952" data-start="929"&gt;membalik proses itu&lt;/strong&gt;.&lt;/p&gt;
&lt;p data-end="971" data-start="955"&gt;Dari noise tadi:&lt;/p&gt;
&lt;ul data-end="1087" data-start="972"&gt;
&lt;li data-end="999" data-section-id="163ps5h" data-start="972"&gt;
AI menebak bentuk awalnya
&lt;/li&gt;
&lt;li data-end="1039" data-section-id="ca3jdg" data-start="1000"&gt;
Sedikit demi sedikit mengurangi noise
&lt;/li&gt;
&lt;li data-end="1087" data-section-id="akqqwa" data-start="1040"&gt;
Sampai akhirnya jadi gambar yang “masuk akal”
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end="1108" data-start="1089"&gt;Proses ini disebut:&lt;/p&gt;
&lt;blockquote data-end="1142" data-start="1109"&gt;
&lt;p data-end="1142" data-start="1111"&gt;&lt;strong data-end="1142" data-start="1111"&gt;Denoising (reverse process)&lt;/strong&gt;&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-end="1147" data-start="1144" /&gt;
&lt;h3 data-end="1171" data-section-id="1es9y3g" data-start="1149"&gt;&#128313; Intinya Gimana?&lt;/h3&gt;
&lt;p data-end="1186" data-start="1173"&gt;Sederhananya:&lt;/p&gt;
&lt;blockquote data-end="1273" data-start="1188"&gt;
&lt;p data-end="1273" data-start="1190"&gt;AI belajar:&lt;br data-end="1204" data-start="1201" /&gt;
“Kalau gambar diacak seperti ini… kira-kira bentuk aslinya apa ya?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end="1351" data-start="1275"&gt;Dan itu dilakukan &lt;strong data-end="1326" data-start="1293"&gt;berulang-ulang (step by step)&lt;/strong&gt; sampai jadi gambar utuh.&lt;/p&gt;
&lt;hr data-end="1356" data-start="1353" /&gt;
&lt;h3 data-end="1389" data-section-id="1yv0nsd" data-start="1358"&gt;&#128313; Kenapa Cara Ini Dipakai?&lt;/h3&gt;
&lt;p data-end="1398" data-start="1391"&gt;Karena:&lt;/p&gt;
&lt;ul data-end="1537" data-start="1399"&gt;
&lt;li data-end="1448" data-section-id="wxytx9" data-start="1399"&gt;
Lebih stabil dibanding langsung generate gambar
&lt;/li&gt;
&lt;li data-end="1492" data-section-id="oqc882" data-start="1449"&gt;
Bisa menghasilkan detail yang lebih halus
&lt;/li&gt;
&lt;li data-end="1537" data-section-id="22wskj" data-start="1493"&gt;
Lebih mudah dikontrol (prompt, style, dll)
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end="1572" data-start="1539"&gt;Makanya teknologi ini dipakai di:&lt;/p&gt;
&lt;ul data-end="1628" data-start="1573"&gt;
&lt;li data-end="1591" data-section-id="101ibt2" data-start="1573"&gt;
Stable Diffusion
&lt;/li&gt;
&lt;li data-end="1600" data-section-id="1v0la9r" data-start="1592"&gt;
DALL·E
&lt;/li&gt;
&lt;li data-end="1628" data-section-id="1m3bce2" data-start="1601"&gt;
Midjourney (konsep mirip)
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end="1633" data-start="1630" /&gt;
&lt;h3 data-end="1648" data-section-id="1v8p29d" data-start="1635"&gt;✨ Penutup&lt;/h3&gt;
&lt;p data-end="1671" data-start="1650"&gt;Awalnya agak aneh ya…&lt;/p&gt;
&lt;blockquote data-end="1723" data-start="1673"&gt;
&lt;p data-end="1723" data-start="1675"&gt;“Kenapa AI harus ngacak dulu baru bikin gambar?”&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p data-end="1808" data-start="1725"&gt;Tapi justru dari situ, AI bisa belajar memahami struktur gambar dengan lebih dalam.&lt;/p&gt;
&lt;hr data-end="1813" data-start="1810" /&gt;
&lt;p data-end="1835" data-start="1815"&gt;Kalau dipikir-pikir…&lt;/p&gt;
&lt;p data-end="1924" data-start="1837"&gt;Ini mirip manusia juga sih &#128516;&lt;br data-end="1869" data-start="1866" /&gt;
Kadang kita harus “bingung dulu”… baru akhirnya ngerti.&lt;/p&gt;&lt;/div&gt;&lt;p&gt;&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://images.openai.com/static-rsc-4/EgofhUBPbiAqOqAYYs5GM2OZOISOGKMkHr9BH7xe2dCL4yJbHrrxDtBbzuMpokWgEkTWNMSwThw302V31eHLmquTD49V-GXl9htYhERbY2yi3T-9_keX6IitNJmDbaA-n8Wd20J3T0M_MW8UBEMYeGJ642HMRU-vXOmOpmj3PcI?purpose=inline" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img border="0" data-original-height="522" data-original-width="1400" height="238" src="https://images.openai.com/static-rsc-4/EgofhUBPbiAqOqAYYs5GM2OZOISOGKMkHr9BH7xe2dCL4yJbHrrxDtBbzuMpokWgEkTWNMSwThw302V31eHLmquTD49V-GXl9htYhERbY2yi3T-9_keX6IitNJmDbaA-n8Wd20J3T0M_MW8UBEMYeGJ642HMRU-vXOmOpmj3PcI?purpose=inline" width="640" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;br /&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;br /&gt;&lt;/div&gt;&lt;br /&gt;&lt;p&gt;&lt;/p&gt;</content><link href="http://it-tude.blogspot.com/feeds/6557682053205245275/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/6557682053205245275" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/6557682053205245275" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/6557682053205245275" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/04/belajar-dasar-ai-cara-ai-noise-denoise.html" rel="alternate" title="Belajar Dasar AI: Cara AI “Noise” - &quot;Denoise&quot;" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/a/AVvXsEg6JfYl7pqD0aj_kLM1rtNeOup3mPPlRre234Qj65iiVsWbNVkX0V7_st_-4544EZE_jDc9d7e2qlP-5gvSjyc3a8STkOXehbgSr1Zdkvx4hDah5eWYEsVZDqTMpvNeK6eSP0l46MRA9SQVnQ_02pOTHu7VTaYz-i-On60Mh_V8uBvOdWMh7dQQ1u6rUv4n=s72-w640-h334-c" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-7443875427686629549</id><published>2026-04-18T15:03:00.000-07:00</published><updated>2026-04-29T03:28:04.962-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="chatbot-it-tude"/><title type="text">Apa Itu Chatbot AI untuk Website?</title><content type="html">&lt;p&gt;Chatbot AI adalah sistem percakapan otomatis yang dapat dipasang pada website untuk membantu menjawab pertanyaan pengunjung.&lt;/p&gt;&lt;p&gt;Berbeda dengan chat biasa, Chatbot AI mampu memahami kalimat, mencari jawaban dari artikel atau data yang dimiliki, lalu memberikan respon yang lebih natural.&lt;/p&gt;&lt;p&gt;Chatbot dapat digunakan untuk:&lt;/p&gt;&lt;ul data-spread="false"&gt;&lt;li&gt;Menjawab pertanyaan pelanggan&lt;/li&gt;&lt;li&gt;Menjelaskan profil perusahaan&lt;/li&gt;&lt;li&gt;Memberikan informasi produk atau layanan&lt;/li&gt;&lt;li&gt;Membantu calon pelanggan menemukan informasi lebih cepat&lt;/li&gt;&lt;li&gt;Membantu proses order atau konsultasi&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Chatbot AI dari it-tude.com dapat dipasang pada website, WhatsApp, maupun sistem internal perusahaan.&lt;/p&gt;&lt;p&gt;Keunggulan utama chatbot bukan hanya karena bisa menjawab otomatis, tetapi karena dapat membantu pelanggan kapan saja, bahkan di luar jam kerja.&lt;/p&gt;</content><link href="http://it-tude.blogspot.com/feeds/7443875427686629549/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/7443875427686629549" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/7443875427686629549" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/7443875427686629549" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/04/apa-itu-chatbot-ai-untuk-website.html" rel="alternate" title="Apa Itu Chatbot AI untuk Website?" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-5013496769529248847</id><published>2026-04-18T07:53:00.000-07:00</published><updated>2026-04-29T04:54:46.639-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="layanan it-tude."/><title type="text">Layanan it-tude.com</title><content type="html">&lt;h1&gt;Layanan it-tude.com&lt;/h1&gt;&lt;p&gt;it-tude.com adalah tempat pengembangan solusi digital yang menggabungkan software, desain, AI, dan digital art untuk kebutuhan bisnis maupun project kreatif.&lt;/p&gt;&lt;p&gt;Bagi kami, teknologi bukan hanya soal membuat sesuatu terlihat modern atau menarik. Tujuan utamanya adalah membuat sesuatu yang benar-benar berguna, mudah dipakai, dan dapat membantu pekerjaan sehari-hari.&lt;/p&gt;&lt;p&gt;it-tude lahir dari pengalaman panjang di dunia teknologi. Jauh sebelum AI menjadi tren seperti sekarang, kami sudah terbiasa membuat berbagai kebutuhan software dan sistem untuk operasional sehari-hari, mulai dari aplikasi kantor, data karyawan, absensi, payroll, hingga sistem medical record.&lt;/p&gt;&lt;p&gt;Sekitar tahun 2007, kami pernah membangun sebuah CV kecil bernama Triiix.com yang menangani pembuatan website, software, networking, troubleshooting, serta kebutuhan IT umum untuk berbagai client. Dari pengalaman tersebut, kami belajar bahwa banyak bisnis sebenarnya tidak membutuhkan sistem yang rumit. Mereka membutuhkan solusi yang sederhana, jelas, mudah digunakan, dan benar-benar membantu.&lt;/p&gt;&lt;p&gt;Karena itu, it-tude.com dibangun bukan sekadar untuk mengikuti tren teknologi. Kami ingin menjadi tempat di mana software dan digital art dapat dipadukan menjadi solusi yang nyata.&lt;/p&gt;&lt;p&gt;Kami percaya bahwa teknologi yang baik harus:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Mudah digunakan&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Membantu pekerjaan menjadi lebih cepat&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Dapat disesuaikan dengan kebutuhan&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Memiliki tampilan yang baik, tetapi tetap fungsional&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Tidak berhenti pada ide, tetapi benar-benar bisa dipakai&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr /&gt;&lt;h1&gt;Tiga Fokus Utama it-tude.com&lt;/h1&gt;&lt;h2&gt;1. Software&lt;/h2&gt;&lt;p&gt;Kami mengembangkan software, aplikasi, dan sistem digital yang dirancang untuk membantu bisnis, pekerjaan lapangan, administrasi, monitoring, maupun kebutuhan operasional.&lt;/p&gt;&lt;p&gt;Fokus kami bukan hanya membuat aplikasi, tetapi membangun sistem yang dapat digunakan dalam jangka panjang.&lt;/p&gt;&lt;p&gt;Beberapa pengembangan yang menjadi bagian dari it-tude.com antara lain:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Sistem patroli digital dan monitoring petugas&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Sistem absensi dan payroll&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Chatbot AI untuk website, WhatsApp, dan kebutuhan internal perusahaan&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Sistem administrasi dan kasir&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Aplikasi monitoring dan dashboard&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Website dan sistem internal perusahaan&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Software yang dapat disesuaikan dengan kebutuhan masing-masing client&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Semua software yang kami kembangkan dirancang agar mudah dipakai, fleksibel, dan dapat berkembang seiring kebutuhan.&lt;/p&gt;&lt;hr /&gt;&lt;h2&gt;2. Digital Art&lt;/h2&gt;&lt;p&gt;Selain software, it-tude.com juga bergerak di bidang digital art dan creative production.&lt;/p&gt;&lt;p&gt;Kami membantu membuat visual, konten, dan media digital yang dapat digunakan untuk promosi, presentasi, branding, hingga project kreatif.&lt;/p&gt;&lt;p&gt;Digital art di it-tude.com tidak hanya berfokus pada tampilan, tetapi juga pada bagaimana visual tersebut dapat menyampaikan pesan dengan lebih baik.&lt;/p&gt;&lt;p&gt;Bidang yang kami kerjakan antara lain:&lt;/p&gt;&lt;ul&gt;&lt;li&gt;&lt;p&gt;Desain visual dan branding&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Pembuatan model 3D&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Product rendering dan visualisasi&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Animasi 3D&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Video berbasis AI&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Konten promosi dan storytelling&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;Digital design untuk kebutuhan bisnis dan media sosial&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p&gt;File untuk 3D printing dan kebutuhan produksi visual lainnya&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Kami percaya bahwa software dan digital art seharusnya saling melengkapi. Sebuah sistem yang baik akan terasa lebih nyaman digunakan jika memiliki visual yang baik. Sebaliknya, visual yang baik akan lebih berguna jika didukung oleh sistem yang benar-benar bekerja.&lt;/p&gt;&lt;p&gt;Karena itulah it-tude.com dibangun dengan dua fondasi utama: Software dan Digital Art.&lt;/p&gt;&lt;p&gt;Keduanya kami gabungkan untuk membantu menciptakan solusi digital yang tidak hanya terlihat baik, tetapi juga benar-benar bermanfaat.&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;h2&gt;3. Mechanical Electrical&lt;/h2&gt;&lt;hr /&gt;&lt;p&gt;&lt;strong&gt;it-tude.com&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;Digitally Your Life. Digitally Yours.&lt;/em&gt;&lt;/p&gt;</content><link href="http://it-tude.blogspot.com/feeds/5013496769529248847/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/5013496769529248847" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/5013496769529248847" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/5013496769529248847" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/04/layanan-it-tudecom.html" rel="alternate" title="Layanan it-tude.com" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-2852535743976090424</id><published>2026-03-31T17:15:00.000-07:00</published><updated>2026-04-13T17:34:35.482-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="Ai"/><category scheme="http://www.blogger.com/atom/ns#" term="art"/><category scheme="http://www.blogger.com/atom/ns#" term="Artificial Intelligence"/><category scheme="http://www.blogger.com/atom/ns#" term="Blender"/><title type="text">Mengenal Berbagai Jenis Shot dalam Sinematografi: Panduan Dasar untuk Artist &amp; Animator</title><content type="html">&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;a href="https://blogger.googleusercontent.com/img/a/AVvXsEhNXFkB42vh0A-X-bH74dcu0ISDR0l_0zlOpxt6mzlPsZjBm2RRYV88L2QXgPGeoPMO9MKB2TCYiZngxKI0-kiAKYXcUnjZ8bZlzmyO6mzduYrfdtZudSQpYzyRhiyVp6Jo8H_hy1BnPHYQn9uJuSRiLJcVLThmKIvCLTWjQmcfxwNc7OjTkkePR-X7FK9_" style="margin-left: 1em; margin-right: 1em;"&gt;&lt;img data-original-height="768" data-original-width="1376" height="179" src="https://blogger.googleusercontent.com/img/a/AVvXsEhNXFkB42vh0A-X-bH74dcu0ISDR0l_0zlOpxt6mzlPsZjBm2RRYV88L2QXgPGeoPMO9MKB2TCYiZngxKI0-kiAKYXcUnjZ8bZlzmyO6mzduYrfdtZudSQpYzyRhiyVp6Jo8H_hy1BnPHYQn9uJuSRiLJcVLThmKIvCLTWjQmcfxwNc7OjTkkePR-X7FK9_=w320-h179" title="Medium Shoot" width="320" /&gt;&lt;/a&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span style="text-align: left;"&gt;&lt;i&gt;Medium Shoot&lt;/i&gt;&lt;/span&gt;&lt;/div&gt;&lt;div class="separator" style="clear: both; text-align: center;"&gt;&lt;span style="text-align: left;"&gt;&lt;br /&gt;&lt;/span&gt;&lt;/div&gt;berikut list shoot Camera yg biasa digunakan dalam Sinematografi&lt;p&gt;&lt;/p&gt;&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;br /&gt;Singkatan&lt;/th&gt;&lt;th&gt;Nama Shot&lt;/th&gt;&lt;th&gt;Penjelasan&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;ECU&lt;/td&gt;&lt;td&gt;Extreme Close Up&lt;/td&gt;&lt;td&gt;Shot sangat dekat, hanya memperlihatkan detail kecil seperti mata, tangan, tekstur kain, tulisan, atau benda tertentu.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;CU&lt;/td&gt;&lt;td&gt;Close Up&lt;/td&gt;&lt;td&gt;Shot dekat, biasanya memperlihatkan wajah atau objek utama secara jelas.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MCU&lt;/td&gt;&lt;td&gt;Medium Close Up&lt;/td&gt;&lt;td&gt;Shot dari dada ke atas. Cocok untuk ekspresi wajah dan sedikit gesture.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MS&lt;/td&gt;&lt;td&gt;Medium Shot&lt;/td&gt;&lt;td&gt;Betul, MS adalah Medium Shot. Biasanya mengambil objek dari pinggang ke atas. Cocok untuk memperlihatkan ekspresi sekaligus gerakan tangan atau interaksi antar orang.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MLS&lt;/td&gt;&lt;td&gt;Medium Long Shot&lt;/td&gt;&lt;td&gt;Shot dari lutut ke atas. Masih terlihat gesture tubuh dan lingkungan sekitar.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;FS&lt;/td&gt;&lt;td&gt;Full Shot&lt;/td&gt;&lt;td&gt;Shot seluruh tubuh dari kepala sampai kaki.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;LS&lt;/td&gt;&lt;td&gt;Long Shot&lt;/td&gt;&lt;td&gt;Shot lebih jauh, memperlihatkan seluruh tubuh dan area sekitar dengan cukup luas.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;ELS&lt;/td&gt;&lt;td&gt;Extreme Long Shot&lt;/td&gt;&lt;td&gt;Shot sangat jauh, biasanya untuk establishing lokasi atau memperlihatkan keramaian dan lingkungan besar.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;OTS&lt;/td&gt;&lt;td&gt;Over The Shoulder&lt;/td&gt;&lt;td&gt;Shot dari belakang bahu seseorang, biasanya untuk percakapan atau melihat arah pandang.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;POV&lt;/td&gt;&lt;td&gt;Point of View&lt;/td&gt;&lt;td&gt;Shot dari sudut pandang seseorang, seolah-olah penonton melihat langsung melalui mata karakter.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Two Shot&lt;/td&gt;&lt;td&gt;Two Shot&lt;/td&gt;&lt;td&gt;Shot yang memperlihatkan dua orang dalam satu frame.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Group Shot&lt;/td&gt;&lt;td&gt;Group Shot&lt;/td&gt;&lt;td&gt;Shot yang memperlihatkan beberapa orang sekaligus dalam satu frame.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Insert Shot&lt;/td&gt;&lt;td&gt;Insert Shot&lt;/td&gt;&lt;td&gt;Shot detail tambahan, misalnya tangan menunjuk, tulisan, kartu identitas, pintu terbuka, dan sebagainya.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Establishing Shot&lt;/td&gt;&lt;td&gt;Establishing Shot&lt;/td&gt;&lt;td&gt;Shot pembuka untuk menunjukkan lokasi atau suasana tempat.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Dolly In&lt;/td&gt;&lt;td&gt;Dolly In&lt;/td&gt;&lt;td&gt;Kamera bergerak perlahan mendekati objek.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Dolly Out&lt;/td&gt;&lt;td&gt;Dolly Out&lt;/td&gt;&lt;td&gt;Kamera bergerak perlahan menjauh dari objek.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Pan&lt;/td&gt;&lt;td&gt;Pan&lt;/td&gt;&lt;td&gt;Kamera bergerak ke kiri atau kanan dari posisi tetap.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tilt&lt;/td&gt;&lt;td&gt;Tilt&lt;/td&gt;&lt;td&gt;Kamera bergerak ke atas atau ke bawah dari posisi tetap.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Tracking Shot&lt;/td&gt;&lt;td&gt;Tracking Shot&lt;/td&gt;&lt;td&gt;Kamera mengikuti pergerakan objek dari samping, depan, atau belakang.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Static Shot&lt;/td&gt;&lt;td&gt;Static Shot&lt;/td&gt;&lt;td&gt;Kamera diam, tidak bergerak.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;</content><link href="http://it-tude.blogspot.com/feeds/2852535743976090424/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/2852535743976090424" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/2852535743976090424" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/2852535743976090424" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/03/mengenal-berbagai-jenis-shot-dalam.html" rel="alternate" title="Mengenal Berbagai Jenis Shot dalam Sinematografi: Panduan Dasar untuk Artist &amp; Animator" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" height="72" url="https://blogger.googleusercontent.com/img/a/AVvXsEhNXFkB42vh0A-X-bH74dcu0ISDR0l_0zlOpxt6mzlPsZjBm2RRYV88L2QXgPGeoPMO9MKB2TCYiZngxKI0-kiAKYXcUnjZ8bZlzmyO6mzduYrfdtZudSQpYzyRhiyVp6Jo8H_hy1BnPHYQn9uJuSRiLJcVLThmKIvCLTWjQmcfxwNc7OjTkkePR-X7FK9_=s72-w320-h179-c" width="72"/><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-6325760765615014691</id><published>2026-03-14T05:09:00.000-07:00</published><updated>2026-04-29T03:30:29.053-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="e-patrol cara login"/><title type="text"> Cara Login ke E-Patrol</title><content type="html">&lt;p&gt;Untuk menggunakan &lt;a href="http://it-tude.com/e-patrol" target="_blank"&gt;E-Patrol apllikasi it-tude&lt;/a&gt;, setiap operator maupun admin harus login terlebih dahulu menggunakan akun yang telah dibuat pada sistem. Login dapat dilakukan melalui browser di komputer maupun smartphone, sehingga petugas dapat langsung mengakses E-Patrol dari lokasi kerja masing-masing.&lt;/p&gt;
&lt;p data-end="533" data-is-last-node="" data-is-only-node="" data-start="315"&gt;Pada panduan ini, kami akan menjelaskan langkah-langkah login ke &lt;a href="http://it-tude.com/e-patrol"&gt;E-Patrol it-tude&lt;/a&gt;, mulai dari membuka halaman login, memasukkan username dan password, hingga solusi jika pengguna lupa password atau tidak dapat masuk ke sistem.&lt;/p&gt;</content><link href="http://it-tude.blogspot.com/feeds/6325760765615014691/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/6325760765615014691" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/6325760765615014691" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/6325760765615014691" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/03/cara-login-ke-e-patrol.html" rel="alternate" title=" Cara Login ke E-Patrol" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-749511155467084894</id><published>2026-03-06T14:34:00.000-08:00</published><updated>2026-04-18T15:35:49.364-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="chatbot"/><category scheme="http://www.blogger.com/atom/ns#" term="it-tude"/><title type="text">Mengapa Website Membutuhkan Chatbot AI?</title><content type="html">&lt;p&gt;&amp;nbsp;Banyak pengunjung website sebenarnya ingin bertanya, tetapi sering kali tidak menemukan informasi dengan cepat.&lt;/p&gt;&lt;p&gt;Mereka ingin tahu:&lt;/p&gt;&lt;ul data-spread="false"&gt;&lt;li&gt;Apa layanan yang tersedia&lt;/li&gt;&lt;li&gt;Berapa harganya&lt;/li&gt;&lt;li&gt;Bagaimana cara order&lt;/li&gt;&lt;li&gt;Apakah bisa konsultasi&lt;/li&gt;&lt;li&gt;Siapa yang bisa dihubungi&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Jika informasi sulit ditemukan, pengunjung biasanya langsung menutup website.&lt;/p&gt;&lt;p&gt;Karena itu, Chatbot AI dapat membantu website menjadi lebih hidup dan lebih mudah digunakan.&lt;/p&gt;&lt;p&gt;Chatbot dapat:&lt;/p&gt;&lt;ul data-spread="false"&gt;&lt;li&gt;Menjawab pertanyaan dalam hitungan detik&lt;/li&gt;&lt;li&gt;Memberi rekomendasi layanan&lt;/li&gt;&lt;li&gt;Mengarahkan pengunjung ke halaman tertentu&lt;/li&gt;&lt;li&gt;Mengumpulkan data calon pelanggan&lt;/li&gt;&lt;li&gt;Membantu meningkatkan peluang penjualan&lt;/li&gt;&lt;/ul&gt;&lt;p&gt;Untuk bisnis kecil maupun besar, chatbot dapat menjadi "admin digital" yang selalu siap membantu.&lt;/p&gt;&lt;p&gt;Label: manfaat chatbot, website bisnis, ai&lt;/p&gt;</content><link href="http://it-tude.blogspot.com/feeds/749511155467084894/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/749511155467084894" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/749511155467084894" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/749511155467084894" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/03/mengapa-website-membutuhkan-chatbot-ai.html" rel="alternate" title="Mengapa Website Membutuhkan Chatbot AI?" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-1319521765232551504</id><published>2026-03-02T12:51:00.000-08:00</published><updated>2026-03-05T15:15:58.977-08:00</updated><title type="text">CSS: Membuat Website Jadi Cantik dan Menarik</title><content type="html">&lt;p&gt;&amp;nbsp;Jika HTML adalah kerangka rumahnya, maka &lt;b data-index-in-node="41" data-path-to-node="4"&gt;CSS (Cascading Style Sheets)&lt;/b&gt; adalah cat tembok, desain interior, dan furniturnya. Tanpa CSS, website kamu hanya akan berisi teks hitam-putih yang membosankan.&lt;/p&gt;&lt;h3 data-path-to-node="5"&gt;Apa itu CSS?&lt;/h3&gt;&lt;p data-path-to-node="6"&gt;CSS adalah bahasa yang digunakan untuk mengatur &lt;b data-index-in-node="48" data-path-to-node="6"&gt;tampilan&lt;/b&gt; elemen HTML. Dengan CSS, kamu bisa mengubah warna teks, jenis font, ukuran gambar, hingga membuat tata letak (layout) yang rapi dan responsif di HP maupun Laptop.&lt;/p&gt;&lt;h3 data-path-to-node="7"&gt;Cara Kerja CSS&lt;/h3&gt;&lt;p data-path-to-node="8"&gt;CSS bekerja dengan cara memilih elemen HTML (Selector) lalu memberinya gaya (Property). Perhatikan contoh sederhana ini:&lt;/p&gt;&lt;response-element ng-version="0.0.0-PLACEHOLDER"&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;code-block _nghost-ng-c2203757349="" class="ng-tns-c2203757349-50 ng-star-inserted"&gt;&lt;!----&gt;&lt;!----&gt;&lt;div _ngcontent-ng-c2203757349="" class="code-block ng-tns-c2203757349-50 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahcKEwie3Jmckv-SAxUAAAAAHQAAAAAQSw" decode-data-ved="1" jslog="223238;track:impression,attention;BardVeMetadataKey:[[&amp;quot;r_c65410e3cc7faaf8&amp;quot;,&amp;quot;c_696a730c4bcb4201&amp;quot;,null,&amp;quot;rc_d2bc62540ef27cef&amp;quot;,null,null,&amp;quot;id&amp;quot;,null,1,null,null,1,0]]"&gt;&lt;div _ngcontent-ng-c2203757349="" class="code-block-decoration header-formatted gds-title-s ng-tns-c2203757349-50 ng-star-inserted"&gt;&lt;span _ngcontent-ng-c2203757349="" class="ng-tns-c2203757349-50"&gt;CSS&lt;/span&gt;&lt;div _ngcontent-ng-c2203757349="" class="buttons ng-tns-c2203757349-50 ng-star-inserted"&gt;&lt;button _ngcontent-ng-c2203757349="" aria-label="Copy code" class="mdc-icon-button mat-mdc-icon-button mat-mdc-button-base mat-mdc-tooltip-trigger copy-button ng-tns-c2203757349-50 mat-unthemed ng-star-inserted" jslog="179062;track:generic_click,impression;BardVeMetadataKey:[[&amp;quot;r_c65410e3cc7faaf8&amp;quot;,&amp;quot;c_696a730c4bcb4201&amp;quot;,null,&amp;quot;rc_d2bc62540ef27cef&amp;quot;,null,null,&amp;quot;id&amp;quot;,null,1,null,null,1,0]];mutable:true" mat-icon-button="" mat-ripple-loader-centered="" mat-ripple-loader-class-name="mat-mdc-button-ripple" mat-ripple-loader-uninitialized="" mattooltip="Copy code"&gt;&lt;span class="mat-mdc-button-persistent-ripple mdc-icon-button__ripple"&gt;&lt;/span&gt;&lt;mat-icon _ngcontent-ng-c2203757349="" aria-hidden="true" class="mat-icon notranslate gds-icon-s google-symbols mat-ligature-font mat-icon-no-color" data-mat-icon-name="content_copy" data-mat-icon-type="font" fonticon="content_copy" role="img"&gt;&lt;/mat-icon&gt;&lt;span class="mat-focus-indicator"&gt;&lt;/span&gt;&lt;span class="mat-mdc-button-touch-target"&gt;&lt;/span&gt;&lt;/button&gt;&lt;!----&gt;&lt;!----&gt;&lt;/div&gt;&lt;!----&gt;&lt;/div&gt;&lt;!----&gt;&lt;div _ngcontent-ng-c2203757349="" class="formatted-code-block-internal-container ng-tns-c2203757349-50"&gt;&lt;div _ngcontent-ng-c2203757349="" class="animated-opacity ng-tns-c2203757349-50"&gt;&lt;pre _ngcontent-ng-c2203757349="" class="ng-tns-c2203757349-50"&gt;&lt;code _ngcontent-ng-c2203757349="" class="code-container formatted ng-tns-c2203757349-50" data-test-id="code-content" role="text"&gt;&lt;span class="hljs-comment"&gt;/* Ini adalah komentar di CSS */&lt;/span&gt;

&lt;span class="hljs-selector-tag"&gt;h1&lt;/span&gt; {
    &lt;span class="hljs-attribute"&gt;color&lt;/span&gt;: blue;           &lt;span class="hljs-comment"&gt;/* Mengubah warna judul jadi biru */&lt;/span&gt;
    &lt;span class="hljs-attribute"&gt;font-size&lt;/span&gt;: &lt;span class="hljs-number"&gt;32px&lt;/span&gt;;       &lt;span class="hljs-comment"&gt;/* Mengubah ukuran huruf */&lt;/span&gt;
    &lt;span class="hljs-attribute"&gt;text-align&lt;/span&gt;: center;    &lt;span class="hljs-comment"&gt;/* Membuat judul ke tengah */&lt;/span&gt;
}

&lt;span class="hljs-selector-tag"&gt;p&lt;/span&gt; {
    &lt;span class="hljs-attribute"&gt;color&lt;/span&gt;: gray;           &lt;span class="hljs-comment"&gt;/* Mengubah warna paragraf jadi abu-abu */&lt;/span&gt;
    &lt;span class="hljs-attribute"&gt;font-family&lt;/span&gt;: Arial;    &lt;span class="hljs-comment"&gt;/* Mengubah jenis huruf */&lt;/span&gt;
}
&lt;/code&gt;&lt;/pre&gt;&lt;!----&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;!----&gt;&lt;!----&gt;&lt;/code-block&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;/response-element&gt;&lt;h3 data-path-to-node="10"&gt;3 Cara Memasang CSS:&lt;/h3&gt;&lt;ol data-path-to-node="11" start="1"&gt;&lt;li&gt;&lt;p data-path-to-node="11,0,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="11,0,0"&gt;Inline CSS:&lt;/b&gt; Langsung di dalam tag HTML.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="11,1,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="11,1,0"&gt;Internal CSS:&lt;/b&gt; Di dalam bagian &lt;code data-index-in-node="30" data-path-to-node="11,1,0"&gt;&amp;lt;head&amp;gt;&lt;/code&gt; file HTML.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="11,2,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="11,2,0"&gt;External CSS:&lt;/b&gt; Menggunakan file terpisah (misal: &lt;code data-index-in-node="48" data-path-to-node="11,2,0"&gt;style.css&lt;/code&gt;). Ini adalah cara paling profesional!&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;-----&lt;br /&gt;ini contoh internal&lt;br /&gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;lt;!DOCTYPE html&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;lt;html lang="id"&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;lt;head&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;meta charset="UTF-8"&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;title&amp;gt;Profil Perkenalanku&amp;lt;/title&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;style&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /* 1. Mengatur gaya untuk seluruh halaman */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; body {&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; background-color: #f0f2f5; /* Warna background abu-abu muda */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; display: flex;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; justify-content: center; /* Membuat konten ke tengah secara horizontal */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; align-items: center;&amp;nbsp; &amp;nbsp; /* Membuat konten ke tengah secara vertikal */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; height: 100vh;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /* Menggunakan tinggi penuh layar */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; margin: 0;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /* 2. Mengatur gaya untuk kartu profil */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .profile-card {&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; background-color: white;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; width: 350px;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; padding: 30px;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; border-radius: 20px; /* Membuat sudut melengkung */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; box-shadow: 0 10px 25px rgba(0,0,0,0.1); /* Memberi efek bayangan halus */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; text-align: center; /* Semua teks di dalam kartu jadi di tengah */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; transition: transform 0.3s ease; /* Efek animasi saat kursor di atasnya */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /* Efek sedikit terangkat saat kartu disentuh kursor */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .profile-card:hover {&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; transform: translateY(-5px);&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /* 3. Mengatur gaya Foto Profil */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .profile-pic {&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; width: 120px;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; height: 120px;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; border-radius: 50%; /* Membuat gambar jadi bulat sempurna */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; object-fit: cover;&amp;nbsp; /* Memastikan gambar tidak gepeng */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; border: 5px solid #007bff; /* Memberi bingkai biru */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; margin-bottom: 20px;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /* 4. Mengatur gaya Nama */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; h1 {&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; font-size: 24px;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; color: #333;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; margin: 0 0 10px 0;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /* 5. Mengatur gaya info (Umur, Hobby) */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .info {&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; font-size: 16px;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; color: #666;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; margin: 5px 0;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .highlight {&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; color: #007bff; /* Warna biru untuk menonjolkan kata kunci */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; font-weight: bold;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /* 6. Mengatur gaya Garis Pembatas */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; hr {&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; border: 0;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; border-top: 1px solid #eee;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; margin: 20px 0;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; /* 7. Mengatur gaya Filsafah Hidup */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .quote-title {&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; font-size: 14px;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; color: #aaa;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; text-transform: uppercase;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; letter-spacing: 1px;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; margin-bottom: 10px;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; .quote {&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; font-style: italic;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; color: #555;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; background-color: #f9f9f9;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; padding: 15px;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; border-radius: 10px;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; border-left: 4px solid #007bff; /* Garis hiasan di sebelah kiri */&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; margin: 0;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; }&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;/style&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;lt;/head&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;lt;body&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;div class="profile-card"&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;img src="https://via.placeholder.com/150" alt="Foto Profil" class="profile-pic"&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;h1&amp;gt;Budi Pratama&amp;lt;/h1&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;p class="info"&amp;gt;Umur: &amp;lt;span class="highlight"&amp;gt;22 Tahun&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;p class="info"&amp;gt;Hoby: &amp;lt;span class="highlight"&amp;gt;Coding, Membaca, Traveling&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;hr&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp;&amp;nbsp;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;p class="quote-title"&amp;gt;Filsafah Hidup&amp;lt;/p&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;blockquote class="quote"&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; "Hari ini harus lebih baik dari kemarin, dan hari esok harus lebih baik dari hari ini."&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;lt;/blockquote&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;nbsp; &amp;nbsp; &amp;lt;/div&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&lt;br /&gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;lt;/body&amp;gt;&lt;/p&gt;&lt;p data-path-to-node="11,2,0"&gt;&amp;lt;/html&amp;gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;br /&gt;&lt;/p&gt;&lt;ol data-path-to-node="16" start="1"&gt;&lt;li&gt;&lt;p data-path-to-node="16,0,0"&gt;&lt;a href="https://it-tude.blogspot.com/2026/03/html-fondasi-dasar-dalam-membangun.html"&gt;&lt;b data-index-in-node="0" data-path-to-node="16,0,0"&gt;HTML (Fondasi Dasar)&lt;/b&gt;&amp;nbsp;-&amp;nbsp;&lt;/a&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="16,1,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="16,1,0"&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;link-block _nghost-ng-c2835501739="" class="ng-star-inserted"&gt;&lt;!----&gt;&lt;!----&gt;CSS (Tampilan Cantik) you are here&lt;!----&gt;&lt;/link-block&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;/b&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="16,2,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="16,2,0"&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;link-block _nghost-ng-c2835501739="" class="ng-star-inserted"&gt;&lt;!----&gt;&lt;!----&gt;&lt;a _ngcontent-ng-c2835501739="" _nghost-ng-c1538880176="" class="ng-star-inserted" data-hveid="0" data-ved="0CAAQ_4QMahcKEwie3Jmckv-SAxUAAAAAHQAAAAAQIQ" decode-data-ved="1" externallink="" href="https://www.google.com/search?q=%23js" jslog="197247;track:generic_click,impression,attention;BardVeMetadataKey:[[&amp;quot;r_8c810d0cbc3e4c44&amp;quot;,&amp;quot;c_696a730c4bcb4201&amp;quot;,null,&amp;quot;rc_f5a7d7451f524ee8&amp;quot;,null,null,&amp;quot;id&amp;quot;,null,1,null,null,1,0]]" rel="noopener" target="_blank"&gt;JavaScript (Logika &amp;amp; Interaksi)&lt;/a&gt;&lt;!----&gt;&lt;/link-block&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;/b&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="16,3,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="16,3,0"&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;link-block _nghost-ng-c2835501739="" class="ng-star-inserted"&gt;&lt;!----&gt;&lt;!----&gt;&lt;a _ngcontent-ng-c2835501739="" _nghost-ng-c1538880176="" class="ng-star-inserted" data-hveid="0" data-ved="0CAAQ_4QMahcKEwie3Jmckv-SAxUAAAAAHQAAAAAQIg" decode-data-ved="1" externallink="" href="https://www.google.com/search?q=%23git" jslog="197247;track:generic_click,impression,attention;BardVeMetadataKey:[[&amp;quot;r_8c810d0cbc3e4c44&amp;quot;,&amp;quot;c_696a730c4bcb4201&amp;quot;,null,&amp;quot;rc_f5a7d7451f524ee8&amp;quot;,null,null,&amp;quot;id&amp;quot;,null,1,null,null,1,0]]" rel="noopener" target="_blank"&gt;Git &amp;amp; GitHub (Simpan Progres)&lt;/a&gt;&lt;!----&gt;&lt;/link-block&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;/b&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="16,4,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="16,4,0"&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;link-block _nghost-ng-c2835501739="" class="ng-star-inserted"&gt;&lt;!----&gt;&lt;!----&gt;&lt;a _ngcontent-ng-c2835501739="" _nghost-ng-c1538880176="" class="ng-star-inserted" data-hveid="0" data-ved="0CAAQ_4QMahcKEwie3Jmckv-SAxUAAAAAHQAAAAAQIw" decode-data-ved="1" externallink="" href="https://www.google.com/search?q=%23framework" jslog="197247;track:generic_click,impression,attention;BardVeMetadataKey:[[&amp;quot;r_8c810d0cbc3e4c44&amp;quot;,&amp;quot;c_696a730c4bcb4201&amp;quot;,null,&amp;quot;rc_f5a7d7451f524ee8&amp;quot;,null,null,&amp;quot;id&amp;quot;,null,1,null,null,1,0]]" rel="noopener" target="_blank"&gt;Framework Frontend (Alat Canggih)&lt;/a&gt;&lt;!----&gt;&lt;/link-block&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;/b&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="16,5,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="16,5,0"&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;link-block _nghost-ng-c2835501739="" class="ng-star-inserted"&gt;&lt;!----&gt;&lt;!----&gt;&lt;a _ngcontent-ng-c2835501739="" _nghost-ng-c1538880176="" class="ng-star-inserted" data-hveid="0" data-ved="0CAAQ_4QMahcKEwie3Jmckv-SAxUAAAAAHQAAAAAQJA" decode-data-ved="1" externallink="" href="https://www.google.com/search?q=%23backend" jslog="197247;track:generic_click,impression,attention;BardVeMetadataKey:[[&amp;quot;r_8c810d0cbc3e4c44&amp;quot;,&amp;quot;c_696a730c4bcb4201&amp;quot;,null,&amp;quot;rc_f5a7d7451f524ee8&amp;quot;,null,null,&amp;quot;id&amp;quot;,null,1,null,null,1,0]]" rel="noopener" target="_blank"&gt;Backend &amp;amp; Database (Penyimpanan Data)&lt;/a&gt;&lt;/link-block&gt;&lt;/b&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;&lt;/li&gt;&lt;/ol&gt;</content><link href="http://it-tude.blogspot.com/feeds/1319521765232551504/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/1319521765232551504" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/1319521765232551504" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/1319521765232551504" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/03/css-membuat-website-jadi-cantik-dan.html" rel="alternate" title="CSS: Membuat Website Jadi Cantik dan Menarik" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-361201131221996197</id><published>2026-03-02T12:48:00.000-08:00</published><updated>2026-03-02T12:48:36.634-08:00</updated><title type="text">HTML: Fondasi Dasar dalam Membangun Website</title><content type="html">&lt;p&gt;Selamat datang di langkah pertama menjadi seorang Web Developer! Jika kita mengibaratkan sebuah website sebagai sebuah bangunan, maka &lt;b data-index-in-node="134" data-path-to-node="5"&gt;HTML (HyperText Markup Language)&lt;/b&gt; adalah kerangka atau struktur batanya. Tanpa HTML, tidak akan ada dinding, pintu, atau jendela.&lt;/p&gt;&lt;h3 data-path-to-node="6"&gt;Apa itu HTML?&lt;/h3&gt;&lt;p data-path-to-node="7"&gt;HTML bukanlah bahasa pemrograman yang rumit seperti matematika, melainkan &lt;b data-index-in-node="74" data-path-to-node="7"&gt;bahasa penanda&lt;/b&gt;. Ia bertugas memberi tahu browser (seperti Chrome atau Safari) bagian mana yang merupakan judul, mana yang paragraf, dan mana yang gambar.&lt;/p&gt;&lt;h3 data-path-to-node="8"&gt;Struktur Dasar HTML&lt;/h3&gt;&lt;p data-path-to-node="9"&gt;Setiap file HTML memiliki susunan standar. Berikut adalah contoh "tulang punggung" kode yang selalu ada:&lt;/p&gt;&lt;response-element class="" ng-version="0.0.0-PLACEHOLDER"&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;code-block _nghost-ng-c2203757349="" class="ng-tns-c2203757349-41 ng-star-inserted"&gt;&lt;!----&gt;&lt;!----&gt;&lt;div _ngcontent-ng-c2203757349="" class="code-block ng-tns-c2203757349-41 ng-animate-disabled ng-trigger ng-trigger-codeBlockRevealAnimation" data-hveid="0" data-ved="0CAAQhtANahcKEwie3Jmckv-SAxUAAAAAHQAAAAAQHw" decode-data-ved="1" jslog="223238;track:impression,attention;BardVeMetadataKey:[[&amp;quot;r_8c810d0cbc3e4c44&amp;quot;,&amp;quot;c_696a730c4bcb4201&amp;quot;,null,&amp;quot;rc_f5a7d7451f524ee8&amp;quot;,null,null,&amp;quot;id&amp;quot;,null,1,null,null,1,0]]"&gt;&lt;div _ngcontent-ng-c2203757349="" class="code-block-decoration header-formatted gds-title-s ng-tns-c2203757349-41 ng-star-inserted"&gt;&lt;span _ngcontent-ng-c2203757349="" class="ng-tns-c2203757349-41"&gt;HTML&lt;/span&gt;&lt;div _ngcontent-ng-c2203757349="" class="buttons ng-tns-c2203757349-41 ng-star-inserted"&gt;&lt;button _ngcontent-ng-c2203757349="" aria-label="Copy code" class="mdc-icon-button mat-mdc-icon-button mat-mdc-button-base mat-mdc-tooltip-trigger copy-button ng-tns-c2203757349-41 mat-unthemed ng-star-inserted" jslog="179062;track:generic_click,impression;BardVeMetadataKey:[[&amp;quot;r_8c810d0cbc3e4c44&amp;quot;,&amp;quot;c_696a730c4bcb4201&amp;quot;,null,&amp;quot;rc_f5a7d7451f524ee8&amp;quot;,null,null,&amp;quot;id&amp;quot;,null,1,null,null,1,0]];mutable:true" mat-icon-button="" mat-ripple-loader-centered="" mat-ripple-loader-class-name="mat-mdc-button-ripple" mat-ripple-loader-uninitialized="" mattooltip="Copy code"&gt;&lt;span class="mat-mdc-button-persistent-ripple mdc-icon-button__ripple"&gt;&lt;/span&gt;&lt;mat-icon _ngcontent-ng-c2203757349="" aria-hidden="true" class="mat-icon notranslate gds-icon-s google-symbols mat-ligature-font mat-icon-no-color" data-mat-icon-name="content_copy" data-mat-icon-type="font" fonticon="content_copy" role="img"&gt;&lt;/mat-icon&gt;&lt;span class="mat-focus-indicator"&gt;&lt;/span&gt;&lt;span class="mat-mdc-button-touch-target"&gt;&lt;/span&gt;&lt;/button&gt;&lt;!----&gt;&lt;!----&gt;&lt;/div&gt;&lt;!----&gt;&lt;/div&gt;&lt;!----&gt;&lt;div _ngcontent-ng-c2203757349="" class="formatted-code-block-internal-container ng-tns-c2203757349-41"&gt;&lt;div _ngcontent-ng-c2203757349="" class="animated-opacity ng-tns-c2203757349-41"&gt;&lt;pre _ngcontent-ng-c2203757349="" class="ng-tns-c2203757349-41"&gt;&lt;code _ngcontent-ng-c2203757349="" class="code-container formatted ng-tns-c2203757349-41" data-test-id="code-content" role="text"&gt;&lt;span class="hljs-meta"&gt;&amp;lt;!DOCTYPE &lt;span class="hljs-meta-keyword"&gt;html&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span class="hljs-tag"&gt;&amp;lt;&lt;span class="hljs-name"&gt;html&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span class="hljs-tag"&gt;&amp;lt;&lt;span class="hljs-name"&gt;head&lt;/span&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="hljs-tag"&gt;&amp;lt;&lt;span class="hljs-name"&gt;title&lt;/span&gt;&amp;gt;&lt;/span&gt;Halaman Pertamaku&lt;span class="hljs-tag"&gt;&amp;lt;/&lt;span class="hljs-name"&gt;title&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span class="hljs-tag"&gt;&amp;lt;/&lt;span class="hljs-name"&gt;head&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span class="hljs-tag"&gt;&amp;lt;&lt;span class="hljs-name"&gt;body&lt;/span&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="hljs-tag"&gt;&amp;lt;&lt;span class="hljs-name"&gt;h1&lt;/span&gt;&amp;gt;&lt;/span&gt;Halo Dunia!&lt;span class="hljs-tag"&gt;&amp;lt;/&lt;span class="hljs-name"&gt;h1&lt;/span&gt;&amp;gt;&lt;/span&gt;
    &lt;span class="hljs-tag"&gt;&amp;lt;&lt;span class="hljs-name"&gt;p&lt;/span&gt;&amp;gt;&lt;/span&gt;Ini adalah paragraf pertama saya di dunia web programming.&lt;span class="hljs-tag"&gt;&amp;lt;/&lt;span class="hljs-name"&gt;p&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span class="hljs-tag"&gt;&amp;lt;/&lt;span class="hljs-name"&gt;body&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;span class="hljs-tag"&gt;&amp;lt;/&lt;span class="hljs-name"&gt;html&lt;/span&gt;&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;!----&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;!----&gt;&lt;!----&gt;&lt;/code-block&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;/response-element&gt;&lt;h3 data-path-to-node="11"&gt;Tag Penting yang Wajib Kamu Tahu:&lt;/h3&gt;&lt;ul data-path-to-node="12"&gt;&lt;li&gt;&lt;p data-path-to-node="12,0,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="12,0,0"&gt;&lt;code data-index-in-node="0" data-path-to-node="12,0,0"&gt;&amp;lt;h1&amp;gt;&lt;/code&gt; sampai &lt;code data-index-in-node="12" data-path-to-node="12,0,0"&gt;&amp;lt;h6&amp;gt;&lt;/code&gt;&lt;/b&gt;: Digunakan untuk judul (Heading).&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="12,1,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="12,1,0"&gt;&lt;code data-index-in-node="0" data-path-to-node="12,1,0"&gt;&amp;lt;p&amp;gt;&lt;/code&gt;&lt;/b&gt;: Digunakan untuk membuat paragraf teks.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="12,2,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="12,2,0"&gt;&lt;code data-index-in-node="0" data-path-to-node="12,2,0"&gt;&amp;lt;a&amp;gt;&lt;/code&gt;&lt;/b&gt;: Digunakan untuk membuat link/tautan ke halaman lain.&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="12,3,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="12,3,0"&gt;&lt;code data-index-in-node="0" data-path-to-node="12,3,0"&gt;&amp;lt;img&amp;gt;&lt;/code&gt;&lt;/b&gt;: Digunakan untuk menampilkan gambar.&lt;/p&gt;&lt;/li&gt;&lt;/ul&gt;&lt;hr data-path-to-node="13" /&gt;&lt;h3 data-path-to-node="14"&gt;&#128640; Lanjut Belajar Materi Berikutnya:&lt;/h3&gt;&lt;p data-path-to-node="15"&gt;&lt;i data-index-in-node="0" data-path-to-node="15"&gt;Klik pada poin di bawah untuk mempelajari lebih lanjut (Pastikan kamu sudah mengikuti urutannya!):&lt;/i&gt;&lt;/p&gt;&lt;ol data-path-to-node="16" start="1"&gt;&lt;li&gt;&lt;p data-path-to-node="16,0,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="16,0,0"&gt;HTML (Fondasi Dasar)&lt;/b&gt; - &lt;i data-index-in-node="23" data-path-to-node="16,0,0"&gt;Kamu berada di sini&lt;/i&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="16,1,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="16,1,0"&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;link-block _nghost-ng-c2835501739="" class="ng-star-inserted"&gt;&lt;!----&gt;&lt;!----&gt;&lt;a _ngcontent-ng-c2835501739="" _nghost-ng-c1538880176="" class="ng-star-inserted" data-hveid="0" data-ved="0CAAQ_4QMahcKEwie3Jmckv-SAxUAAAAAHQAAAAAQIA" decode-data-ved="1" externallink="" href="https://www.google.com/search?q=%23css" jslog="197247;track:generic_click,impression,attention;BardVeMetadataKey:[[&amp;quot;r_8c810d0cbc3e4c44&amp;quot;,&amp;quot;c_696a730c4bcb4201&amp;quot;,null,&amp;quot;rc_f5a7d7451f524ee8&amp;quot;,null,null,&amp;quot;id&amp;quot;,null,1,null,null,1,0]]" rel="noopener" target="_blank"&gt;CSS (Tampilan Cantik)&lt;/a&gt;&lt;!----&gt;&lt;/link-block&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;/b&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="16,2,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="16,2,0"&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;link-block _nghost-ng-c2835501739="" class="ng-star-inserted"&gt;&lt;!----&gt;&lt;!----&gt;&lt;a _ngcontent-ng-c2835501739="" _nghost-ng-c1538880176="" class="ng-star-inserted" data-hveid="0" data-ved="0CAAQ_4QMahcKEwie3Jmckv-SAxUAAAAAHQAAAAAQIQ" decode-data-ved="1" externallink="" href="https://www.google.com/search?q=%23js" jslog="197247;track:generic_click,impression,attention;BardVeMetadataKey:[[&amp;quot;r_8c810d0cbc3e4c44&amp;quot;,&amp;quot;c_696a730c4bcb4201&amp;quot;,null,&amp;quot;rc_f5a7d7451f524ee8&amp;quot;,null,null,&amp;quot;id&amp;quot;,null,1,null,null,1,0]]" rel="noopener" target="_blank"&gt;JavaScript (Logika &amp;amp; Interaksi)&lt;/a&gt;&lt;!----&gt;&lt;/link-block&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;/b&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="16,3,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="16,3,0"&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;link-block _nghost-ng-c2835501739="" class="ng-star-inserted"&gt;&lt;!----&gt;&lt;!----&gt;&lt;a _ngcontent-ng-c2835501739="" _nghost-ng-c1538880176="" class="ng-star-inserted" data-hveid="0" data-ved="0CAAQ_4QMahcKEwie3Jmckv-SAxUAAAAAHQAAAAAQIg" decode-data-ved="1" externallink="" href="https://www.google.com/search?q=%23git" jslog="197247;track:generic_click,impression,attention;BardVeMetadataKey:[[&amp;quot;r_8c810d0cbc3e4c44&amp;quot;,&amp;quot;c_696a730c4bcb4201&amp;quot;,null,&amp;quot;rc_f5a7d7451f524ee8&amp;quot;,null,null,&amp;quot;id&amp;quot;,null,1,null,null,1,0]]" rel="noopener" target="_blank"&gt;Git &amp;amp; GitHub (Simpan Progres)&lt;/a&gt;&lt;!----&gt;&lt;/link-block&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;/b&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="16,4,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="16,4,0"&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;link-block _nghost-ng-c2835501739="" class="ng-star-inserted"&gt;&lt;!----&gt;&lt;!----&gt;&lt;a _ngcontent-ng-c2835501739="" _nghost-ng-c1538880176="" class="ng-star-inserted" data-hveid="0" data-ved="0CAAQ_4QMahcKEwie3Jmckv-SAxUAAAAAHQAAAAAQIw" decode-data-ved="1" externallink="" href="https://www.google.com/search?q=%23framework" jslog="197247;track:generic_click,impression,attention;BardVeMetadataKey:[[&amp;quot;r_8c810d0cbc3e4c44&amp;quot;,&amp;quot;c_696a730c4bcb4201&amp;quot;,null,&amp;quot;rc_f5a7d7451f524ee8&amp;quot;,null,null,&amp;quot;id&amp;quot;,null,1,null,null,1,0]]" rel="noopener" target="_blank"&gt;Framework Frontend (Alat Canggih)&lt;/a&gt;&lt;!----&gt;&lt;/link-block&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;/b&gt;&lt;/p&gt;&lt;/li&gt;&lt;li&gt;&lt;p data-path-to-node="16,5,0"&gt;&lt;b data-index-in-node="0" data-path-to-node="16,5,0"&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;!----&gt;&lt;link-block _nghost-ng-c2835501739="" class="ng-star-inserted"&gt;&lt;!----&gt;&lt;!----&gt;&lt;a _ngcontent-ng-c2835501739="" _nghost-ng-c1538880176="" class="ng-star-inserted" data-hveid="0" data-ved="0CAAQ_4QMahcKEwie3Jmckv-SAxUAAAAAHQAAAAAQJA" decode-data-ved="1" externallink="" href="https://www.google.com/search?q=%23backend" jslog="197247;track:generic_click,impression,attention;BardVeMetadataKey:[[&amp;quot;r_8c810d0cbc3e4c44&amp;quot;,&amp;quot;c_696a730c4bcb4201&amp;quot;,null,&amp;quot;rc_f5a7d7451f524ee8&amp;quot;,null,null,&amp;quot;id&amp;quot;,null,1,null,null,1,0]]" rel="noopener" target="_blank"&gt;Backend &amp;amp; Database (Penyimpanan Data)&lt;/a&gt;&lt;/link-block&gt;&lt;/b&gt;&lt;/p&gt;&lt;/li&gt;&lt;/ol&gt;</content><link href="http://it-tude.blogspot.com/feeds/361201131221996197/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/361201131221996197" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/361201131221996197" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/361201131221996197" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/03/html-fondasi-dasar-dalam-membangun.html" rel="alternate" title="HTML: Fondasi Dasar dalam Membangun Website" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-3128819497496324626</id><published>2026-02-15T08:36:00.000-08:00</published><updated>2026-02-15T08:36:08.866-08:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="command"/><category scheme="http://www.blogger.com/atom/ns#" term="ssh"/><title type="text">Login ke VPS Tanpa Password</title><content type="html">&lt;p&gt;&amp;nbsp;&lt;/p&gt;&lt;h2 data-end="245" data-start="174"&gt;Cara Login ke VPS Tanpa Password Menggunakan SSH Key (Best Practice)&lt;/h2&gt;
&lt;p data-end="474" data-start="247"&gt;Jika kamu mengelola VPS, &lt;strong data-end="355" data-start="272"&gt;menggunakan SSH Key adalah metode login paling aman dan paling direkomendasikan&lt;/strong&gt;.&lt;br data-end="359" data-start="356" /&gt;
Metode ini sudah menjadi &lt;strong data-end="404" data-start="384"&gt;standar industri&lt;/strong&gt; karena jauh lebih aman dibandingkan login menggunakan password biasa.&lt;/p&gt;
&lt;p data-end="491" data-start="476"&gt;Dengan SSH Key:&lt;/p&gt;
&lt;ul data-end="615" data-start="492"&gt;
&lt;li data-end="534" data-start="492"&gt;
&lt;p data-end="534" data-start="494"&gt;Tidak perlu mengetik password saat login&lt;/p&gt;
&lt;/li&gt;
&lt;li data-end="579" data-start="535"&gt;
&lt;p data-end="579" data-start="537"&gt;Risiko brute-force attack jauh lebih kecil&lt;/p&gt;
&lt;/li&gt;
&lt;li data-end="615" data-start="580"&gt;
&lt;p data-end="615" data-start="582"&gt;Akses lebih cepat dan profesional&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end="620" data-start="617" /&gt;
&lt;h2 data-end="646" data-start="622"&gt;Kenapa Harus SSH Key?&lt;/h2&gt;
&lt;p data-end="796" data-start="648"&gt;✅ Lebih aman dari password&lt;br data-end="677" data-start="674" /&gt;
✅ Tidak bisa ditebak atau di-bruteforce&lt;br data-end="719" data-start="716" /&gt;
✅ Cocok untuk server produksi&lt;br data-end="751" data-start="748" /&gt;
✅ Dipakai oleh hampir semua sysadmin &amp;amp; DevOps&lt;/p&gt;
&lt;hr data-end="801" data-start="798" /&gt;
&lt;h2 data-end="827" data-start="803"&gt;Gambaran Alur SSH Key&lt;/h2&gt;
&lt;ol data-end="934" data-start="829"&gt;
&lt;li data-end="857" data-start="829"&gt;
&lt;p data-end="857" data-start="832"&gt;Membuat SSH key di laptop&lt;/p&gt;
&lt;/li&gt;
&lt;li data-end="891" data-start="858"&gt;
&lt;p data-end="891" data-start="861"&gt;Mengirim &lt;strong data-end="884" data-start="870"&gt;public key&lt;/strong&gt; ke VPS&lt;/p&gt;
&lt;/li&gt;
&lt;li data-end="934" data-start="892"&gt;
&lt;p data-end="934" data-start="895"&gt;Login dari laptop ke VPS tanpa password&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;hr data-end="939" data-start="936" /&gt;
&lt;h2 data-end="980" data-start="941"&gt;Step-by-Step Setup SSH Key (Windows)&lt;/h2&gt;
&lt;h3 data-end="1014" data-start="982"&gt;1. Membuat SSH Key di Laptop&lt;/h3&gt;
&lt;p data-end="1085" data-start="1016"&gt;Buka &lt;strong data-end="1035" data-start="1021"&gt;PowerShell&lt;/strong&gt; atau &lt;strong data-end="1059" data-start="1041"&gt;Command Prompt&lt;/strong&gt; di laptop, lalu jalankan:&lt;/p&gt;
&lt;pre class="overflow-visible! px-0!" data-end="1120" data-start="1087"&gt;&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;&lt;div class="sticky top-[calc(var(--sticky-padding-top)+9*var(--spacing))]"&gt;&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-bash"&gt;&lt;span&gt;&lt;span&gt;ssh-keygen -t ed25519
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;&lt;/pre&gt;
&lt;p data-end="1135" data-start="1122"&gt;Saat diminta:&lt;/p&gt;
&lt;ul data-end="1242" data-start="1136"&gt;
&lt;li data-end="1170" data-start="1136"&gt;
&lt;p data-end="1170" data-start="1138"&gt;Tekan &lt;strong data-end="1153" data-start="1144"&gt;Enter&lt;/strong&gt; (lokasi default)&lt;/p&gt;
&lt;/li&gt;
&lt;li data-end="1219" data-start="1171"&gt;
&lt;p data-end="1219" data-start="1173"&gt;Tekan &lt;strong data-end="1188" data-start="1179"&gt;Enter&lt;/strong&gt; (passphrase boleh dikosongkan)&lt;/p&gt;
&lt;/li&gt;
&lt;li data-end="1242" data-start="1220"&gt;
&lt;p data-end="1242" data-start="1222"&gt;Tekan &lt;strong data-end="1237" data-start="1228"&gt;Enter&lt;/strong&gt; lagi&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end="1283" data-start="1244"&gt;SSH key akan dibuat otomatis di folder:&lt;/p&gt;
&lt;pre class="overflow-visible! px-0!" data-end="1316" data-start="1285"&gt;&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;&lt;div class="sticky top-[calc(var(--sticky-padding-top)+9*var(--spacing))]"&gt;&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre!"&gt;&lt;span&gt;&lt;span&gt;&lt;span class="hljs-section"&gt;C:\Users\NamaUser\.ssh\&lt;/span&gt;&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;&lt;/pre&gt;
&lt;p data-end="1338" data-start="1318"&gt;Isi folder tersebut:&lt;/p&gt;
&lt;ul data-end="1462" data-start="1339"&gt;
&lt;li data-end="1397" data-start="1339"&gt;
&lt;p data-end="1397" data-start="1341"&gt;&lt;code data-end="1353" data-start="1341"&gt;id_ed25519&lt;/code&gt; → &lt;strong data-end="1371" data-start="1356"&gt;PRIVATE KEY&lt;/strong&gt; (jangan pernah dibagikan)&lt;/p&gt;
&lt;/li&gt;
&lt;li data-end="1462" data-start="1398"&gt;
&lt;p data-end="1462" data-start="1400"&gt;&lt;code data-end="1416" data-start="1400"&gt;id_ed25519.pub&lt;/code&gt; → &lt;strong data-end="1433" data-start="1419"&gt;PUBLIC KEY&lt;/strong&gt; (ini yang dikirim ke server)&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;hr data-end="1467" data-start="1464" /&gt;
&lt;h3 data-end="1495" data-start="1469"&gt;2. Menyalin Public Key&lt;/h3&gt;
&lt;p data-end="1546" data-start="1497"&gt;Tampilkan isi public key dengan perintah berikut:&lt;/p&gt;
&lt;pre class="overflow-visible! px-0!" data-end="1598" data-start="1548"&gt;&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;&lt;div class="sticky top-[calc(var(--sticky-padding-top)+9*var(--spacing))]"&gt;&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-bash"&gt;&lt;span&gt;&lt;span&gt;&lt;span class="hljs-built_in"&gt;type&lt;/span&gt;&lt;/span&gt;&lt;span&gt; %USERPROFILE%\.ssh\id_ed25519.pub
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;&lt;/pre&gt;
&lt;p data-end="1647" data-start="1600"&gt;Hasilnya berupa &lt;strong data-end="1638" data-start="1616"&gt;satu baris panjang&lt;/strong&gt;, contoh:&lt;/p&gt;
&lt;pre class="overflow-visible! px-0!" data-end="1709" data-start="1649"&gt;&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;&lt;div class="sticky top-[calc(var(--sticky-padding-top)+9*var(--spacing))]"&gt;&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre!"&gt;&lt;span&gt;&lt;span&gt;ssh&lt;/span&gt;&lt;span&gt;&lt;span class="hljs-operator"&gt;-&lt;/span&gt;&lt;/span&gt;&lt;span&gt;ed25519 AAAAC3NzaC1lZDI1NTE5AAAAI... &lt;/span&gt;&lt;span&gt;&lt;span class="hljs-keyword"&gt;user&lt;/span&gt;&lt;/span&gt;&lt;span&gt;&lt;span class="hljs-variable"&gt;@laptop&lt;/span&gt;&lt;/span&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;&lt;/pre&gt;
&lt;p data-end="1783" data-start="1711"&gt;&#128073; &lt;strong data-end="1736" data-start="1714"&gt;Copy seluruh baris&lt;/strong&gt; (jangan dipotong, jangan ada enter di tengah).&lt;/p&gt;
&lt;hr data-end="1788" data-start="1785" /&gt;
&lt;h3 data-end="1830" data-start="1790"&gt;3. Masuk ke VPS via Console Provider&lt;/h3&gt;
&lt;p data-end="1925" data-start="1832"&gt;Karena SSH belum aktif, kita gunakan &lt;strong data-end="1900" data-start="1869"&gt;console bawaan provider VPS&lt;/strong&gt; (misalnya Open Console).&lt;/p&gt;
&lt;p data-end="1940" data-start="1927"&gt;Langkah umum:&lt;/p&gt;
&lt;ul data-end="2039" data-start="1941"&gt;
&lt;li data-end="1961" data-start="1941"&gt;
&lt;p data-end="1961" data-start="1943"&gt;Buka dashboard VPS&lt;/p&gt;
&lt;/li&gt;
&lt;li data-end="1985" data-start="1962"&gt;
&lt;p data-end="1985" data-start="1964"&gt;Klik &lt;strong data-end="1985" data-start="1969"&gt;Open Console&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li data-end="2039" data-start="1986"&gt;
&lt;p data-end="2039" data-start="1988"&gt;Login menggunakan &lt;strong data-end="2025" data-start="2006"&gt;username server&lt;/strong&gt; yang tersedia&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;blockquote data-end="2105" data-start="2041"&gt;
&lt;p data-end="2105" data-start="2043"&gt;Metode ini aman karena aksesnya hanya dari dashboard provider.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;hr data-end="2110" data-start="2107" /&gt;
&lt;h3 data-end="2148" data-start="2112"&gt;4. Menambahkan Public Key ke VPS&lt;/h3&gt;
&lt;p data-end="2198" data-start="2150"&gt;Di dalam VPS console, jalankan perintah berikut:&lt;/p&gt;
&lt;pre class="overflow-visible! px-0!" data-end="2255" data-start="2200"&gt;&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;&lt;div class="sticky top-[calc(var(--sticky-padding-top)+9*var(--spacing))]"&gt;&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-bash"&gt;&lt;span&gt;&lt;span&gt;&lt;span class="hljs-built_in"&gt;mkdir&lt;/span&gt;&lt;/span&gt;&lt;span&gt; -p ~/.ssh
nano ~/.ssh/authorized_keys
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;&lt;/pre&gt;
&lt;ul data-end="2371" data-start="2257"&gt;
&lt;li data-end="2316" data-start="2257"&gt;
&lt;p data-end="2316" data-start="2259"&gt;Paste &lt;strong data-end="2279" data-start="2265"&gt;public key&lt;/strong&gt; yang sudah kamu copy (1 baris penuh)&lt;/p&gt;
&lt;/li&gt;
&lt;li data-end="2371" data-start="2317"&gt;
&lt;p data-end="2333" data-start="2319"&gt;Simpan dengan:&lt;/p&gt;
&lt;ul data-end="2371" data-start="2336"&gt;
&lt;li data-end="2356" data-start="2336"&gt;
&lt;p data-end="2356" data-start="2338"&gt;&lt;code data-end="2348" data-start="2338"&gt;CTRL + O&lt;/code&gt; → Enter&lt;/p&gt;
&lt;/li&gt;
&lt;li data-end="2371" data-start="2359"&gt;
&lt;p data-end="2371" data-start="2361"&gt;&lt;code data-end="2371" data-start="2361"&gt;CTRL + X&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p data-end="2405" data-start="2373"&gt;Atur permission (ini &lt;strong data-end="2403" data-start="2394"&gt;WAJIB&lt;/strong&gt;):&lt;/p&gt;
&lt;pre class="overflow-visible! px-0!" data-end="2468" data-start="2407"&gt;&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;&lt;div class="sticky top-[calc(var(--sticky-padding-top)+9*var(--spacing))]"&gt;&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-bash"&gt;&lt;span&gt;&lt;span&gt;&lt;span class="hljs-built_in"&gt;chmod&lt;/span&gt;&lt;/span&gt;&lt;span&gt; 700 ~/.ssh
&lt;/span&gt;&lt;span&gt;&lt;span class="hljs-built_in"&gt;chmod&lt;/span&gt;&lt;/span&gt;&lt;span&gt; 600 ~/.ssh/authorized_keys
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;&lt;/pre&gt;
&lt;hr data-end="2473" data-start="2470" /&gt;
&lt;h3 data-end="2508" data-start="2475"&gt;5. Test Login SSH dari Laptop&lt;/h3&gt;
&lt;p data-end="2558" data-start="2510"&gt;Kembali ke PowerShell / CMD di laptop, jalankan:&lt;/p&gt;
&lt;pre class="overflow-visible! px-0!" data-end="2591" data-start="2560"&gt;&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;&lt;div class="sticky top-[calc(var(--sticky-padding-top)+9*var(--spacing))]"&gt;&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-bash"&gt;&lt;span&gt;&lt;span&gt;ssh username@IP_VPS
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;&lt;/pre&gt;
&lt;p data-end="2600" data-start="2593"&gt;Contoh:&lt;/p&gt;
&lt;pre class="overflow-visible! px-0!" data-end="2637" data-start="2601"&gt;&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;&lt;div class="sticky top-[calc(var(--sticky-padding-top)+9*var(--spacing))]"&gt;&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-bash"&gt;&lt;span&gt;&lt;span&gt;ssh user@xxx.xxx.xxx.xxx
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;&lt;/pre&gt;
&lt;p data-end="2712" data-start="2639"&gt;Jika berhasil, kamu akan langsung masuk ke server tanpa diminta password:&lt;/p&gt;
&lt;pre class="overflow-visible! px-0!" data-end="2740" data-start="2714"&gt;&lt;div class="contain-inline-size rounded-2xl corner-superellipse/1.1 relative bg-token-sidebar-surface-primary"&gt;&lt;div class="sticky top-[calc(var(--sticky-padding-top)+9*var(--spacing))]"&gt;&lt;div class="absolute end-0 bottom-0 flex h-9 items-center pe-2"&gt;&lt;div class="bg-token-bg-elevated-secondary text-token-text-secondary flex items-center gap-4 rounded-sm px-2 font-sans text-xs"&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;div class="overflow-y-auto p-4" dir="ltr"&gt;&lt;code class="whitespace-pre! language-bash"&gt;&lt;span&gt;&lt;span&gt;user@server:~$
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/div&gt;&lt;/div&gt;&lt;/pre&gt;
&lt;p data-end="2776" data-start="2742"&gt;&#127881; &lt;strong data-end="2776" data-start="2745"&gt;SSH berhasil tanpa password&lt;/strong&gt;&lt;/p&gt;
&lt;hr data-end="2781" data-start="2778" /&gt;
&lt;h2 data-end="2802" data-start="2783"&gt;Catatan Keamanan&lt;/h2&gt;
&lt;ul data-end="2973" data-start="2804"&gt;
&lt;li data-end="2851" data-start="2804"&gt;
&lt;p data-end="2851" data-start="2806"&gt;Jangan pernah membagikan file &lt;strong data-end="2851" data-start="2836"&gt;private key&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li data-end="2897" data-start="2852"&gt;
&lt;p data-end="2897" data-start="2854"&gt;Public key aman untuk ditempatkan di server&lt;/p&gt;
&lt;/li&gt;
&lt;li data-end="2973" data-start="2898"&gt;
&lt;p data-end="2973" data-start="2900"&gt;Setelah SSH Key aktif, &lt;strong data-end="2973" data-start="2923"&gt;sangat disarankan menonaktifkan login password&lt;/strong&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;</content><link href="http://it-tude.blogspot.com/feeds/3128819497496324626/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/3128819497496324626" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/3128819497496324626" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/3128819497496324626" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/02/login-ke-vps-tanpa-password.html" rel="alternate" title="Login ke VPS Tanpa Password" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry><entry><id>tag:blogger.com,1999:blog-1506668875974051482.post-430858623520618235</id><published>2026-02-07T14:36:00.000-08:00</published><updated>2026-04-18T15:42:01.651-07:00</updated><category scheme="http://www.blogger.com/atom/ns#" term="chatbot"/><category scheme="http://www.blogger.com/atom/ns#" term="it-tude"/><title type="text">Chatbot AI it-tude.com : Menjawab Berdasarkan Data</title><content type="html">&lt;p data-end="159" data-start="0"&gt;Salah satu kelebihan Chatbot AI dari it-tude.com adalah kemampuannya menjawab berdasarkan dokumen, website, dan data yang dimiliki perusahaan atau rumah sakit.&lt;/p&gt;&lt;p data-end="295" data-start="161"&gt;Artinya, chatbot tidak hanya memberikan jawaban umum, tetapi dapat menjawab sesuai informasi yang sudah tersedia dan terus diperbarui.&lt;/p&gt;&lt;p data-end="336" data-start="297"&gt;Data yang digunakan dapat berasal dari:&lt;/p&gt;&lt;ul data-end="465" data-start="338"&gt;
&lt;li data-end="355" data-section-id="klfoyd" data-start="338"&gt;
Halaman website
&lt;/li&gt;
&lt;li data-end="379" data-section-id="1ydcnn0" data-start="356"&gt;
Jadwal praktek dokter
&lt;/li&gt;
&lt;li data-end="385" data-section-id="1o4jha" data-start="380"&gt;
FAQ
&lt;/li&gt;
&lt;li data-end="409" data-section-id="xpaf7v" data-start="386"&gt;
Data kamar rawat inap
&lt;/li&gt;
&lt;li data-end="424" data-section-id="1ovqfqv" data-start="410"&gt;
Data antrian
&lt;/li&gt;
&lt;li data-end="444" data-section-id="1efit7u" data-start="425"&gt;
Database internal
&lt;/li&gt;
&lt;li data-end="465" data-section-id="805zei" data-start="445"&gt;
Sistem rumah sakit
&lt;/li&gt;
&lt;/ul&gt;&lt;p data-end="508" data-start="467"&gt;Chatbot dapat mempelajari dua jenis data:&lt;/p&gt;&lt;ul data-end="739" data-start="510"&gt;
&lt;li data-end="586" data-section-id="f041d2" data-start="510"&gt;
Data statis, misalnya profil rumah sakit, daftar layanan, alamat, atau FAQ
&lt;/li&gt;
&lt;li data-end="739" data-section-id="qji140" data-start="587"&gt;
Data dinamis, yaitu data yang berubah setiap saat, misalnya jadwal praktek dokter hari ini, kamar yang masih tersedia, nomor antrian, atau jadwal poli
&lt;/li&gt;
&lt;/ul&gt;&lt;p data-end="888" data-start="741"&gt;Contohnya, jika rumah sakit memiliki halaman jadwal dokter atau database internal, maka chatbot dapat mengambil informasi tersebut secara otomatis.&lt;/p&gt;&lt;p data-end="919" data-start="890"&gt;Misalnya pengunjung bertanya:&lt;/p&gt;&lt;p data-end="973" data-start="921"&gt;“Jam berapa dokter spesialis anak praktek hari ini?”&lt;/p&gt;&lt;p data-end="1003" data-start="975"&gt;Maka chatbot dapat menjawab:&lt;/p&gt;&lt;p data-end="1087" data-start="1005"&gt;“dr. Andi Pratama, Sp.A praktek hari ini pukul 09.00–12.00 di Poli Anak lantai 2.”&lt;/p&gt;&lt;p data-end="1119" data-start="1089"&gt;Atau jika pengunjung bertanya:&lt;/p&gt;&lt;p data-end="1155" data-start="1121"&gt;“Apakah kamar VIP masih tersedia?”&lt;/p&gt;&lt;p data-end="1185" data-start="1157"&gt;Maka chatbot dapat menjawab:&lt;/p&gt;&lt;p data-end="1258" data-start="1187"&gt;“Saat ini kamar VIP tersisa 2 kamar dan kamar kelas 1 tersisa 5 kamar.”&lt;/p&gt;&lt;p&gt;














&lt;/p&gt;&lt;p data-end="1454" data-is-last-node="" data-is-only-node="" data-start="1260"&gt;Dengan cara ini, chatbot tidak hanya berfungsi sebagai penjawab FAQ, tetapi juga dapat menjadi asisten digital yang membantu pasien atau pengunjung mendapatkan informasi secara cepat dan akurat.&lt;/p&gt;</content><link href="http://it-tude.blogspot.com/feeds/430858623520618235/comments/default" rel="replies" title="Posting Komentar" type="application/atom+xml"/><link href="http://www.blogger.com/comment/fullpage/post/1506668875974051482/430858623520618235" rel="replies" title="0 Komentar" type="text/html"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/430858623520618235" rel="edit" type="application/atom+xml"/><link href="http://www.blogger.com/feeds/1506668875974051482/posts/default/430858623520618235" rel="self" type="application/atom+xml"/><link href="http://it-tude.blogspot.com/2026/02/chatbot-ai-it-tudecom-menjawab.html" rel="alternate" title="Chatbot AI it-tude.com : Menjawab Berdasarkan Data" type="text/html"/><author><name>Unknown</name><email>noreply@blogger.com</email><gd:image height="16" rel="http://schemas.google.com/g/2005#thumbnail" src="https://img1.blogblog.com/img/b16-rounded.gif" width="16"/></author><thr:total>0</thr:total></entry></feed>